ca65 V2.18 - Debian 2.19-2
Main file   : prg.s
Current file: prg.s

000000r 1               ; Balloon Fight - ca65 PRG disassembly
000000r 1               ; 16 KiB NROM PRG mapped at CPU $C000-$FFFF
000000r 1               ; Hardware register and controller symbols are provided by symbols.inc.
000000r 1               .setcpu "6502"
000000r 1               .include "symbols.inc"
000000r 2               ; PPU registers
000000r 2               PPUCTRL = $2000
000000r 2               PPUMASK = $2001
000000r 2               PPUSTATUS = $2002
000000r 2               OAMADDR = $2003
000000r 2               OAMDATA = $2004
000000r 2               PPUSCROLL = $2005
000000r 2               PPUADDR = $2006
000000r 2               PPUDATA = $2007
000000r 2               OAMDMA = $4014
000000r 2               JOY1 = $4016
000000r 2               JOY2 = $4017
000000r 2               
000000r 2               APUPC1BASE = $4000
000000r 2               APUPC1SWEEP = $4001
000000r 2               APUPC1TLOW = $4002
000000r 2               APUPC1THIGH = $4003
000000r 2               
000000r 2               APUPC2BASE = $4004
000000r 2               APUPC2SWEEP = $4005
000000r 2               APUPC2LOW = $4006
000000r 2               APUPC2HIGH = $4007
000000r 2               
000000r 2               APUTRIBASE = $4008
000000r 2               APUTRILOW = $400A
000000r 2               APUTRIHIGH = $400B
000000r 2               
000000r 2               APUNOISEBASE = $400C
000000r 2               APUNOISELOOP = $400E
000000r 2               APUNOISELENGTH = $400F
000000r 2               
000000r 2               APUDMABASE = $4010
000000r 2               APUDMALOAD = $4011
000000r 2               APUDMAADDR = $4012
000000r 2               APUDMALEN = $4013
000000r 2               
000000r 2               APUCTRL = $4015
000000r 2               APUSTATUS = $4015
000000r 2               APUFRAMECNT = $4017
000000r 2               
000000r 2               ; Controller Masks
000000r 2               PAD_RIGHT=$01
000000r 2               PAD_LEFT=$02
000000r 2               PAD_DOWN=$04
000000r 2               PAD_UP=$08
000000r 2               PAD_START=$10
000000r 2               PAD_SELECT=$20
000000r 2               PAD_B=$40
000000r 2               PAD_A=$80
000000r 2               PAD_HORIZONTAL=PAD_LEFT|PAD_RIGHT
000000r 2               PAD_VERTICAL=PAD_UP|PAD_DOWN
000000r 2               PAD_DPAD=PAD_HORIZONTAL|PAD_VERTICAL
000000r 2               
000000r 1               .include "locals.inc"
000000r 2               ; ============================================================================
000000r 2               ; Confirmed and high-confidence zero-page symbols
000000r 2               ; ============================================================================
000000r 2               
000000r 2               IndirectPtrLo           = $00
000000r 2               IndirectPtrHi           = $01
000000r 2               RecordPtrLo             = $02
000000r 2               RecordPtrHi             = $03
000000r 2               
000000r 2               MathTemp05              = $05
000000r 2               NmiSavedX               = $0D
000000r 2               NmiSavedY               = $0E
000000r 2               DerivedControl0         = $0F
000000r 2               
000000r 2               ControllerHeld1         = $11
000000r 2               ControllerHeld2         = $12
000000r 2               InputState1             = $13
000000r 2               InputState2             = $14
000000r 2               ControllerPressed1      = $15
000000r 2               ControllerPressed2      = $16
000000r 2               InputAux1               = $17
000000r 2               InputAux2               = $18
000000r 2               
000000r 2               RandomStateLo           = $19
000000r 2               RandomStateHi           = $1A
000000r 2               TransitionCounter       = $1B
000000r 2               TransitionActive        = $1D
000000r 2               SessionActive           = $1E
000000r 2               NmiStateFlag            = $1F
000000r 2               FrameState20            = $20
000000r 2               SelectedPitchAction     = $21
000000r 2               
000000r 2               SavedIndex              = $22
000000r 2               InlineReturnLo          = $26
000000r 2               InlineReturnHi          = $27
000000r 2               
000000r 2               SelectionValue0         = $32
000000r 2               RoundStateIndex         = $33
000000r 2               PlayerOneSelection      = $34
000000r 2               PlayerTwoSelection      = $35
000000r 2               
000000r 2               ObjectScreenX           = $36
000000r 2               ObjectScreenXHi         = $37
000000r 2               ObjectScreenY           = $38
000000r 2               ObjectScreenYHi         = $39
000000r 2               
000000r 2               PpuQueueOffset          = $3E
000000r 2               OamWriteOffset          = $3F
000000r 2               
000000r 2               ModeFlags               = $40
000000r 2               CurrentObjectArrayOffset= $42
000000r 2               SelectionState          = $43
000000r 2               PlayerSelectionActive   = $44
000000r 2               MatchCompleteFlag       = $45
000000r 2               StateSequenceActive     = $46
000000r 2               
000000r 2               DelayCounter            = $48
000000r 2               LoopCounter49           = $49
000000r 2               QueueDestination        = $4A
000000r 2               ActivePlayerSide        = $4B
000000r 2               HorizontalDirectionMask           = $4C
000000r 2               
000000r 2               RandomState0            = $4D
000000r 2               RandomState1            = $4E
000000r 2               RandomBits0             = $4F
000000r 2               RandomBits1             = $50
000000r 2               Counter51               = $51
000000r 2               Counter52               = $52
000000r 2               
000000r 2               SavedBaseXLo            = $53
000000r 2               SavedBaseXHi            = $54
000000r 2               SavedBaseYLo            = $55
000000r 2               SavedBaseYHi            = $56
000000r 2               
000000r 2               BaseMotionActive            = $5C
000000r 2               BaseMotionPhase             = $5D
000000r 2               BaseMotionEventCount        = $5E
000000r 2               TrajectoryResult            = $5F
000000r 2               
000000r 2               PendingStateTransition  = $60
000000r 2               UpdateCounter           = $61
000000r 2               PrimarySequenceState    = $62
000000r 2               TransitionSequenceState = $63
000000r 2               SecondarySequenceState  = $64
000000r 2               PendingScoreIncrement        = $65
000000r 2               InningOrSharedScore     = $66
000000r 2               PlayerOneScore          = $67
000000r 2               PlayerTwoScore          = $68
000000r 2               EventWriteIndex         = $69
000000r 2               EventReadIndex          = $6A
000000r 2               TextCopyCount           = $6B
000000r 2               SpecialSequenceState    = $6D
000000r 2               ObjectTransitionState   = $6E
000000r 2               PendingEvent            = $6F
000000r 2               
000000r 2               TableCopyIndex          = $70
000000r 2               DisplayCounterValue            = $71
000000r 2               StateSelector           = $72
000000r 2               WindupLoopCounter         = $73
000000r 2               MotionSettledCountdown  = $76
000000r 2               StateTimer78            = $78
000000r 2               
000000r 2               ActionSequenceCounter   = $7E
000000r 2               SelectedStateCount      = $7F
000000r 2               RandomValue81           = $81
000000r 2               ActorActionComplete     = $82
000000r 2               ObjectApproachCount     = $83
000000r 2               ObjectApproachDirectionFlag          = $84
000000r 2               TrajectoryEvaluationEnabled = $86
000000r 2               ObjectProximityState    = $87
000000r 2               MotionDirectionState    = $88
000000r 2               
000000r 2               FielderAnimationCountdown = $8C
000000r 2               FielderInputBalance     = $8D
000000r 2               RandomHorizontalMotion  = $8E
000000r 2               CalculatedVerticalMotion= $8F
000000r 2               RandomVerticalMotion    = $90
000000r 2               PitchDirectionDecision  = $91
000000r 2               ActionDelayCounter      = $92
000000r 2               PitchUpdateDelay        = $94
000000r 2               
000000r 2               CurrentActionState      = $9D
000000r 2               SecondaryActorState0    = $9F
000000r 2               SecondaryActorState1    = $A0
000000r 2               SecondaryActorState2    = $A1
000000r 2               ObjectSequenceState     = $A2
000000r 2               ObjectSelectionLowerBound= $A5
000000r 2               
000000r 2               CalculatedCoordinateLow = $AE
000000r 2               CalculatedCoordinateHigh= $AF
000000r 2               
000000r 2               PositionSignState       = $B7
000000r 2               ObjectListFlag          = $C7
000000r 2               SpriteSortBaseIndex     = $C9
000000r 2               SpriteArrayEnd          = $CA
000000r 2               
000000r 2               MathShiftCount          = $DB
000000r 2               
000000r 2               PpuCtrlShadow           = $DD
000000r 2               PpuMaskShadow           = $DE
000000r 2               ScrollX                 = $DF
000000r 2               ScrollY                 = $E0
000000r 2               
000000r 2               CurrentObjectIndex      = $E1
000000r 2               ScriptDepth             = $E2
000000r 2               FrameCounter            = $E3
000000r 2               
000000r 2               GameplaySuspended       = $EF
000000r 2               SoundPtrLo              = $F6
000000r 2               SoundPtrHi              = $F7
000000r 2               
000000r 2               PendingAudioFlags       = $FE
000000r 2               RenderStateFlags        = $FF
000000r 2               
000000r 1               
000000r 1               ; ============================================================================
000000r 1               ; Zero-page scratch policy
000000r 1               ;
000000r 1               ; $00-$0C are intentionally left numeric. Their meanings vary between pointer
000000r 1               ; decoding, arithmetic, OAM construction, geometry, PPU streaming, and audio.
000000r 1               ; Routine contracts describe the local role when it can be inferred safely.
000000r 1               ; ============================================================================
000000r 1               .segment "PRG"
000000r 1               .org $C000
00C000  1               
00C000  1               ; ============================================================================
00C000  1               ; $C000-$C023
00C000  1               ; Title-screen copyright PPU stream.
00C000  1               ; ============================================================================
00C000  1               
00C000  1               TitleCopyrightPpuStream:        ; $C000
00C000  1  23 45 05         .byte $23,$45,$05
00C003  1  AF 01 09 08      .byte $AF,$01,$09,$08,$04
00C007  1  04           
00C008  1               
00C008  1  23 65 18         .byte $23,$65,$18
00C00B  1  17 12 17 1D      .byte $17,$12,$17,$1D,$0E,$17,$0D,$18
00C00F  1  0E 17 0D 18  
00C013  1  25 18 0F 25      .byte $25,$18,$0F,$25,$0A,$16,$0E,$1B
00C017  1  0A 16 0E 1B  
00C01B  1  12 0C 0A 25      .byte $12,$0C,$0A,$25,$12,$17,$0C,$AC
00C01F  1  12 17 0C AC  
00C023  1               
00C023  1  00               .byte $00
00C024  1               
00C024  1               ; ============================================================================
00C024  1               ; $C024-$C029
00C024  1               ; Tile values for the six selectable team initials: A, C, D, P, R, Y.
00C024  1               ; ============================================================================
00C024  1               
00C024  1               TeamInitialTileTable:           ; $C024
00C024  1  0A 0C 0D 19      .byte $0A,$0C,$0D,$19,$1B,$22
00C028  1  1B 22        
00C02A  1               
00C02A  1               ; ============================================================================
00C02A  1               ; $C02A-$C02F
00C02A  1               ; Sprite tile selected for each team-selection marker.
00C02A  1               ; ============================================================================
00C02A  1               
00C02A  1               TeamSelectionSpriteTileTable:   ; $C02A
00C02A  1  0C 16 12 16      .byte $0C,$16,$12,$16,$03,$0F
00C02E  1  03 0F        
00C030  1               
00C030  1               ; ============================================================================
00C030  1               ; $C030-$C035
00C030  1               ; X coordinate used for each team-selection marker sprite.
00C030  1               ; ============================================================================
00C030  1               
00C030  1               TeamSelectionSpriteXTable:      ; $C030
00C030  1  30 21 10 30      .byte $30,$21,$10,$30,$21,$10
00C034  1  21 10        
00C036  1               
00C036  1               ; ============================================================================
00C036  1               ; $C036-$C045
00C036  1               ; Calculate randomized signed pitch motion.
00C036  1               ; ============================================================================
00C036  1               
00C036  1               CalculateRandomizedPitchMotion: ; $C036
00C036  1  A9 E2            lda #$E2                    ; $C036: A9 E2
00C038  1  ED 39 05         sbc $0539                   ; $C038: ED 39 05
00C03B  1               
00C03B  1  C9 80            cmp #$80                    ; $C03B: C9 80
00C03D  1  6A               ror                         ; $C03D: 6A
00C03E  1               
00C03E  1  C9 80            cmp #$80                    ; $C03E: C9 80
00C040  1  6A               ror                         ; $C040: 6A
00C041  1               
00C041  1  38               sec                         ; $C041: 38
00C042  1  ED 39 05         sbc $0539                   ; $C042: ED 39 05
00C045  1               
00C045  1  60               rts                         ; $C045: 60
00C046  1               
00C046  1               ; ============================================================================
00C046  1               ; $C046-$C122
00C046  1               ; NMI handler
00C046  1               ; ============================================================================
00C046  1               
00C046  1               NMI:                            ; $C046
00C046  1  48               pha                         ; $C046: 48
00C047  1  86 0D            stx NmiSavedX               ; $C047: 86 0D
00C049  1  84 0E            sty NmiSavedY               ; $C049: 84 0E
00C04B  1               
00C04B  1  AD 02 20         lda PPUSTATUS               ; $C04B: AD 02 20
00C04E  1               
00C04E  1  A9 02            lda #$02                    ; $C04E: A9 02
00C050  1  8D 14 40         sta OAMDMA                  ; $C050: 8D 14 40
00C053  1               
00C053  1  A0 00            ldy #$00                    ; $C053: A0 00
00C055  1               
00C055  1               NMI_PacketLoop:                 ; $C055
00C055  1  BE 00 03         ldx $0300,y                 ; $C055: BE 00 03
00C058  1  F0 33            beq NMI_QueueDone           ; $C058: F0 33
00C05A  1               
00C05A  1  C8               iny                         ; $C05A: C8
00C05B  1               
00C05B  1  B9 00 03         lda $0300,y                 ; $C05B: B9 00 03
00C05E  1  8D 06 20         sta PPUADDR                 ; $C05E: 8D 06 20
00C061  1               
00C061  1  C8               iny                         ; $C061: C8
00C062  1               
00C062  1  B9 00 03         lda $0300,y                 ; $C062: B9 00 03
00C065  1  8D 06 20         sta PPUADDR                 ; $C065: 8D 06 20
00C068  1               
00C068  1  C8               iny                         ; $C068: C8
00C069  1  C8               iny                         ; $C069: C8
00C06A  1               
00C06A  1  B9 FF 02         lda $02FF,y                 ; $C06A: B9 FF 02
00C06D  1  8D 00 20         sta PPUCTRL                 ; $C06D: 8D 00 20
00C070  1               
00C070  1  30 0C            bmi NMI_ReadPacket          ; $C070: 30 0C
00C072  1               
00C072  1               NMI_WritePacket:                ; $C072
00C072  1  B9 00 03         lda $0300,y                 ; $C072: B9 00 03
00C075  1  8D 07 20         sta PPUDATA                 ; $C075: 8D 07 20
00C078  1               
00C078  1  C8               iny                         ; $C078: C8
00C079  1  CA               dex                         ; $C079: CA
00C07A  1               
00C07A  1  D0 F6            bne NMI_WritePacket         ; $C07A: D0 F6
00C07C  1  F0 D7            beq NMI_PacketLoop          ; $C07C: F0 D7
00C07E  1               
00C07E  1               NMI_ReadPacket:                 ; $C07E
00C07E  1  AD 07 20         lda PPUDATA                 ; $C07E: AD 07 20
00C081  1                                               ; Discard buffered PPU read.
00C081  1               
00C081  1               NMI_ReadPacketLoop:             ; $C081
00C081  1  AD 07 20         lda PPUDATA                 ; $C081: AD 07 20
00C084  1  99 00 03         sta $0300,y                 ; $C084: 99 00 03
00C087  1               
00C087  1  C8               iny                         ; $C087: C8
00C088  1  CA               dex                         ; $C088: CA
00C089  1               
00C089  1  D0 F6            bne NMI_ReadPacketLoop      ; $C089: D0 F6
00C08B  1  F0 C8            beq NMI_PacketLoop          ; $C08B: F0 C8
00C08D  1               
00C08D  1               NMI_QueueDone:                  ; $C08D
00C08D  1  8E 00 03         stx $0300                   ; $C08D: 8E 00 03
00C090  1               
00C090  1  A5 DF            lda ScrollX                 ; $C090: A5 DF
00C092  1  8D 05 20         sta PPUSCROLL               ; $C092: 8D 05 20
00C095  1               
00C095  1  A5 E0            lda ScrollY                 ; $C095: A5 E0
00C097  1  8D 05 20         sta PPUSCROLL               ; $C097: 8D 05 20
00C09A  1               
00C09A  1  A5 DE            lda PpuMaskShadow           ; $C09A: A5 DE
00C09C  1  8D 01 20         sta PPUMASK                 ; $C09C: 8D 01 20
00C09F  1               
00C09F  1  A5 DD            lda PpuCtrlShadow           ; $C09F: A5 DD
00C0A1  1  8D 00 20         sta PPUCTRL                 ; $C0A1: 8D 00 20
00C0A4  1               
00C0A4  1  20 D0 F9         jsr InitializeAudioEngine   ; $C0A4: 20 D0 F9
00C0A7  1               
00C0A7  1  A9 01            lda #$01                    ; $C0A7: A9 01
00C0A9  1  8D 16 40         sta JOY1                    ; $C0A9: 8D 16 40
00C0AC  1               
00C0AC  1  A9 00            lda #$00                    ; $C0AC: A9 00
00C0AE  1  8D 16 40         sta JOY1                    ; $C0AE: 8D 16 40
00C0B1  1               
00C0B1  1  A2 08            ldx #$08                    ; $C0B1: A2 08
00C0B3  1               
00C0B3  1               NMI_ReadControllers:            ; $C0B3
00C0B3  1  AD 16 40         lda JOY1                    ; $C0B3: AD 16 40
00C0B6  1  29 03            and #$03                    ; $C0B6: 29 03
00C0B8  1  C9 01            cmp #$01                    ; $C0B8: C9 01
00C0BA  1  26 15            rol ControllerPressed1      ; $C0BA: 26 15
00C0BC  1               
00C0BC  1  AD 17 40         lda JOY2                    ; $C0BC: AD 17 40
00C0BF  1  29 03            and #$03                    ; $C0BF: 29 03
00C0C1  1  C9 01            cmp #$01                    ; $C0C1: C9 01
00C0C3  1  26 16            rol ControllerPressed2      ; $C0C3: 26 16
00C0C5  1               
00C0C5  1  CA               dex                         ; $C0C5: CA
00C0C6  1  D0 EB            bne NMI_ReadControllers     ; $C0C6: D0 EB
00C0C8  1               
00C0C8  1  A2 01            ldx #$01                    ; $C0C8: A2 01
00C0CA  1               
00C0CA  1               NMI_UpdateControllerState:      ; $C0CA
00C0CA  1  B5 15            lda ControllerPressed1,x    ; $C0CA: B5 15
00C0CC  1  A8               tay                         ; $C0CC: A8
00C0CD  1               
00C0CD  1  55 11            eor ControllerHeld1,x       ; $C0CD: 55 11
00C0CF  1  35 15            and ControllerPressed1,x    ; $C0CF: 35 15
00C0D1  1               
00C0D1  1  95 15            sta ControllerPressed1,x    ; $C0D1: 95 15
00C0D3  1  94 11            sty ControllerHeld1,x       ; $C0D3: 94 11
00C0D5  1               
00C0D5  1  CA               dex                         ; $C0D5: CA
00C0D6  1  10 F2            bpl NMI_UpdateControllerState
00C0D8  1                                               ; $C0D6: 10 F2
00C0D8  1               
00C0D8  1  29 10            and #$10                    ; $C0D8: 29 10
00C0DA  1  F0 10            beq NMI_CheckState          ; $C0DA: F0 10
00C0DC  1               
00C0DC  1  A5 1E            lda SessionActive           ; $C0DC: A5 1E
00C0DE  1  D0 07            bne NMI_RunCommand0B        ; $C0DE: D0 07
00C0E0  1               
00C0E0  1  85 1D            sta TransitionActive        ; $C0E0: 85 1D
00C0E2  1  85 EF            sta GameplaySuspended          ; $C0E2: 85 EF
00C0E4  1               
00C0E4  1  4C 9C C4         jmp InitializeNewSession            ; $C0E4: 4C 9C C4
00C0E7  1               
00C0E7  1               NMI_RunCommand0B:               ; $C0E7
00C0E7  1  A2 0B            ldx #$0B                    ; $C0E7: A2 0B
00C0E9  1  20 2A EB         jsr ProcessQueuedObjectEvent; $C0E9: 20 2A EB
00C0EC  1               
00C0EC  1               NMI_CheckState:                 ; $C0EC
00C0EC  1  A5 1F            lda NmiStateFlag            ; $C0EC: A5 1F
00C0EE  1  D0 2C            bne NMI_RestoreRegisters    ; $C0EE: D0 2C
00C0F0  1               
00C0F0  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $C0F0: 20 0A EB
00C0F3  1               
00C0F3  1                   ; Inline command data consumed by the routine at QueueInlineObjectEvent.
00C0F3  1                   ; These bytes must not be assembled as 6502 instructions.
00C0F3  1  05 21 C1         .byte $05,$21,$C1           ; $C0F3-$C0F5
00C0F6  1               
00C0F6  1  A2 00            ldx #$00                    ; $C0F6: A2 00
00C0F8  1  20 2A EB         jsr ProcessQueuedObjectEvent                   ; $C0F8: 20 2A EB
00C0FB  1               
00C0FB  1  E6 E3            inc FrameCounter            ; $C0FB: E6 E3
00C0FD  1  20 7E C8         jsr CalculateControllerAssignments                   ; $C0FD: 20 7E C8
00C100  1               
00C100  1  A6 0F            ldx DerivedControl0         ; $C100: A6 0F
00C102  1  8A               txa                         ; $C102: 8A
00C103  1  A8               tay                         ; $C103: A8
00C104  1               
00C104  1  F0 04            beq NMI_StoreFirstObject    ; $C104: F0 04
00C106  1               
00C106  1  B5 10            lda $10,x                   ; $C106: B5 10
00C108  1  B4 14            ldy InputState2,x           ; $C108: B4 14
00C10A  1               
00C10A  1               NMI_StoreFirstObject:           ; $C10A
00C10A  1  85 13            sta InputState1             ; $C10A: 85 13
00C10C  1  84 17            sty InputAux1               ; $C10C: 84 17
00C10E  1               
00C10E  1  A6 10            ldx $10                     ; $C10E: A6 10
00C110  1  8A               txa                         ; $C110: 8A
00C111  1  A8               tay                         ; $C111: A8
00C112  1               
00C112  1  F0 04            beq NMI_StoreSecondObject   ; $C112: F0 04
00C114  1               
00C114  1  B5 10            lda $10,x                   ; $C114: B5 10
00C116  1  B4 14            ldy InputState2,x           ; $C116: B4 14
00C118  1               
00C118  1               NMI_StoreSecondObject:          ; $C118
00C118  1  85 14            sta InputState2             ; $C118: 85 14
00C11A  1  84 18            sty InputAux2               ; $C11A: 84 18
00C11C  1               
00C11C  1               NMI_RestoreRegisters:           ; $C11C
00C11C  1  A4 0E            ldy NmiSavedY               ; $C11C: A4 0E
00C11E  1  A6 0D            ldx NmiSavedX               ; $C11E: A6 0D
00C120  1               
00C120  1  68               pla                         ; $C120: 68
00C121  1  40               rti                         ; $C121: 40
00C122  1               
00C122  1               ; ============================================================================
00C122  1               ; $C122-$C18C
00C122  1               ; Main-frame initialization, timer updates, and 16-bit position updates
00C122  1               ; ============================================================================
00C122  1               
00C122  1               UpdateFrameObjectsAndTimers:                   ; $C122
00C122  1  A2 00            ldx #$00                    ; $C122: A2 00
00C124  1               
00C124  1  86 3E            stx PpuQueueOffset          ; $C124: 86 3E
00C126  1  86 3F            stx OamWriteOffset          ; $C126: 86 3F
00C128  1  86 20            stx FrameState20            ; $C128: 86 20
00C12A  1               
00C12A  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $C12A: 20 0A EB
00C12D  1               
00C12D  1                   ; Inline command data consumed by the routine at QueueInlineObjectEvent.
00C12D  1  07 64 C2         .byte $07,$64,$C2           ; $C12D-$C12F
00C130  1               
00C130  1  A2 01            ldx #$01                    ; $C130: A2 01
00C132  1  20 2A EB         jsr ProcessQueuedObjectEvent                   ; $C132: 20 2A EB
00C135  1               
00C135  1  A2 30            ldx #$30                    ; $C135: A2 30
00C137  1               
00C137  1               UpdateObjectTimerLoop:         ; $C137
00C137  1  BD 3F 06         lda $063F,x                 ; $C137: BD 3F 06
00C13A  1  F0 08            beq UpdateNextObjectTimer  ; $C13A: F0 08
00C13C  1               
00C13C  1  DE 3F 06         dec $063F,x                 ; $C13C: DE 3F 06
00C13F  1  D0 03            bne UpdateNextObjectTimer  ; $C13F: D0 03
00C141  1               
00C141  1  20 15 EB         jsr QueueDecodedObjectEventSelectIndex                   ; $C141: 20 15 EB
00C144  1               
00C144  1               UpdateNextObjectTimer:         ; $C144
00C144  1  CA               dex                         ; $C144: CA
00C145  1  D0 F0            bne UpdateObjectTimerLoop  ; $C145: D0 F0
00C147  1               
00C147  1  A2 03            ldx #$03                    ; $C147: A2 03
00C149  1               
00C149  1               UpdateShortCountdowns:    ; $C149
00C149  1  DE AD 05         dec $05AD,x                 ; $C149: DE AD 05
00C14C  1  10 03            bpl UpdateNextShortCountdown
00C14E  1                                               ; $C14C: 10 03
00C14E  1               
00C14E  1  FE AD 05         inc $05AD,x                 ; $C14E: FE AD 05
00C151  1               
00C151  1               UpdateNextShortCountdown:       ; $C151
00C151  1  CA               dex                         ; $C151: CA
00C152  1  10 F5            bpl UpdateShortCountdowns
00C154  1                                               ; $C152: 10 F5
00C154  1               
00C154  1  A5 1D            lda TransitionActive        ; $C154: A5 1D
00C156  1  F0 03            beq IntegrateAllObjectPositions
00C158  1                                               ; $C156: F0 03
00C158  1               
00C158  1  4C 6A EB         jmp CommonEngineExit                   ; $C158: 4C 6A EB
00C15B  1               
00C15B  1               IntegrateAllObjectPositions:   ; $C15B
00C15B  1  A2 24            ldx #$24                    ; $C15B: A2 24
00C15D  1               
00C15D  1                   ; Each logical object occupies two adjacent indices.
00C15D  1                   ; X advances by two after both coordinate pairs are updated.
00C15D  1               
00C15D  1               IntegrateObjectPositionLoop:      ; $C15D
00C15D  1  A0 00            ldy #$00                    ; $C15D: A0 00
00C15F  1               
00C15F  1  BD 6F 05         lda $056F,x                 ; $C15F: BD 6F 05
00C162  1  10 01            bpl AddObjectHorizontalDelta       ; $C162: 10 01
00C164  1               
00C164  1  88               dey                         ; $C164: 88
00C165  1                                               ; Sign-extend the low-byte delta.
00C165  1               
00C165  1               AddObjectHorizontalDelta:              ; $C165
00C165  1  18               clc                         ; $C165: 18
00C166  1               
00C166  1  7D 0B 05         adc $050B,x                 ; $C166: 7D 0B 05
00C169  1  9D 0B 05         sta $050B,x                 ; $C169: 9D 0B 05
00C16C  1               
00C16C  1  98               tya                         ; $C16C: 98
00C16D  1  7D 0C 05         adc $050C,x                 ; $C16D: 7D 0C 05
00C170  1  9D 0C 05         sta $050C,x                 ; $C170: 9D 0C 05
00C173  1               
00C173  1  A0 00            ldy #$00                    ; $C173: A0 00
00C175  1               
00C175  1  BD 70 05         lda $0570,x                 ; $C175: BD 70 05
00C178  1  10 01            bpl AddObjectVerticalDelta       ; $C178: 10 01
00C17A  1               
00C17A  1  88               dey                         ; $C17A: 88
00C17B  1                                               ; Sign-extend the second delta.
00C17B  1               
00C17B  1               AddObjectVerticalDelta:              ; $C17B
00C17B  1  18               clc                         ; $C17B: 18
00C17C  1               
00C17C  1  7D 3C 05         adc $053C,x                 ; $C17C: 7D 3C 05
00C17F  1  9D 3C 05         sta $053C,x                 ; $C17F: 9D 3C 05
00C182  1               
00C182  1  98               tya                         ; $C182: 98
00C183  1  7D 3D 05         adc $053D,x                 ; $C183: 7D 3D 05
00C186  1  9D 3D 05         sta $053D,x                 ; $C186: 9D 3D 05
00C189  1               
00C189  1  CA               dex                         ; $C189: CA
00C18A  1  CA               dex                         ; $C18A: CA
00C18B  1               
00C18B  1  10 D0            bpl IntegrateObjectPositionLoop
00C18D  1                                               ; $C18B: 10 D0
00C18D  1               
00C18D  1               ; ============================================================================
00C18D  1               ; $C18D-$C264
00C18D  1               ; Object processing, signed coordinate adjustment, and state handling
00C18D  1               ; ============================================================================
00C18D  1               
00C18D  1               UpdateBaseMotionSequence:                   ; $C18D
00C18D  1  A2 00            ldx #$00                    ; $C18D: A2 00
00C18F  1  20 CA C3         jsr IntegrateObjectVelocityAndPosition            ; $C18F: 20 CA C3
00C192  1               
00C192  1  A2 31            ldx #$31                    ; $C192: A2 31
00C194  1  20 CA C3         jsr IntegrateObjectVelocityAndPosition            ; $C194: 20 CA C3
00C197  1               
00C197  1  A2 62            ldx #$62                    ; $C197: A2 62
00C199  1  20 CA C3         jsr IntegrateObjectVelocityAndPosition            ; $C199: 20 CA C3
00C19C  1               
00C19C  1  AD 6C 05         lda $056C                   ; $C19C: AD 6C 05
00C19F  1  30 03            bmi ReflectBaseMotionValues
00C1A1  1                                               ; $C19F: 30 03
00C1A1  1               
00C1A1  1  4C 28 C2         jmp UpdatePositionSignState            ; $C1A1: 4C 28 C2
00C1A4  1               
00C1A4  1               ; ----------------------------------------------------------------------------
00C1A4  1               ; Negate the signed values at $056B/$056C and $0569/$056A.
00C1A4  1               ; The second result is divided by two using LSR/ROR.
00C1A4  1               ; ----------------------------------------------------------------------------
00C1A4  1               
00C1A4  1               ReflectBaseMotionValues:      ; $C1A4
00C1A4  1  A0 00            ldy #$00                    ; $C1A4: A0 00
00C1A6  1  38               sec                         ; $C1A6: 38
00C1A7  1               
00C1A7  1  98               tya                         ; $C1A7: 98
00C1A8  1  ED 6B 05         sbc $056B                   ; $C1A8: ED 6B 05
00C1AB  1  8D 6B 05         sta $056B                   ; $C1AB: 8D 6B 05
00C1AE  1               
00C1AE  1  98               tya                         ; $C1AE: 98
00C1AF  1  ED 6C 05         sbc $056C                   ; $C1AF: ED 6C 05
00C1B2  1  8D 6C 05         sta $056C                   ; $C1B2: 8D 6C 05
00C1B5  1               
00C1B5  1  38               sec                         ; $C1B5: 38
00C1B6  1               
00C1B6  1  98               tya                         ; $C1B6: 98
00C1B7  1  ED 69 05         sbc $0569                   ; $C1B7: ED 69 05
00C1BA  1  8D 69 05         sta $0569                   ; $C1BA: 8D 69 05
00C1BD  1               
00C1BD  1  98               tya                         ; $C1BD: 98
00C1BE  1  ED 6A 05         sbc $056A                   ; $C1BE: ED 6A 05
00C1C1  1               
00C1C1  1  4A               lsr                         ; $C1C1: 4A
00C1C2  1  8D 6A 05         sta $056A                   ; $C1C2: 8D 6A 05
00C1C5  1  6E 69 05         ror $0569                   ; $C1C5: 6E 69 05
00C1C8  1               
00C1C8  1               ; ----------------------------------------------------------------------------
00C1C8  1               ; Subtract twice the signed value in $0508 from $0507/$0508.
00C1C8  1               ; ----------------------------------------------------------------------------
00C1C8  1               
00C1C8  1  A0 00            ldy #$00                    ; $C1C8: A0 00
00C1CA  1               
00C1CA  1  AD 08 05         lda $0508                   ; $C1CA: AD 08 05
00C1CD  1  10 01            bpl DoubleHorizontalVelocity
00C1CF  1                                               ; $C1CD: 10 01
00C1CF  1               
00C1CF  1  88               dey                         ; $C1CF: 88
00C1D0  1               
00C1D0  1               DoubleHorizontalVelocity:       ; $C1D0
00C1D0  1  0A               asl                         ; $C1D0: 0A
00C1D1  1  85 07            sta $07                     ; $C1D1: 85 07
00C1D3  1               
00C1D3  1  98               tya                         ; $C1D3: 98
00C1D4  1  2A               rol                         ; $C1D4: 2A
00C1D5  1  85 08            sta $08                     ; $C1D5: 85 08
00C1D7  1               
00C1D7  1  38               sec                         ; $C1D7: 38
00C1D8  1               
00C1D8  1  AD 07 05         lda $0507                   ; $C1D8: AD 07 05
00C1DB  1  E5 07            sbc $07                     ; $C1DB: E5 07
00C1DD  1  8D 07 05         sta $0507                   ; $C1DD: 8D 07 05
00C1E0  1               
00C1E0  1  AD 08 05         lda $0508                   ; $C1E0: AD 08 05
00C1E3  1  E5 08            sbc $08                     ; $C1E3: E5 08
00C1E5  1  8D 08 05         sta $0508                   ; $C1E5: 8D 08 05
00C1E8  1               
00C1E8  1               ; ----------------------------------------------------------------------------
00C1E8  1               ; Repeat the signed adjustment for $0538/$0539.
00C1E8  1               ; ----------------------------------------------------------------------------
00C1E8  1               
00C1E8  1  A0 00            ldy #$00                    ; $C1E8: A0 00
00C1EA  1               
00C1EA  1  AD 39 05         lda $0539                   ; $C1EA: AD 39 05
00C1ED  1  10 01            bpl DoubleVerticalVelocity
00C1EF  1                                               ; $C1ED: 10 01
00C1EF  1               
00C1EF  1  88               dey                         ; $C1EF: 88
00C1F0  1               
00C1F0  1               DoubleVerticalVelocity:      ; $C1F0
00C1F0  1  0A               asl                         ; $C1F0: 0A
00C1F1  1  85 07            sta $07                     ; $C1F1: 85 07
00C1F3  1               
00C1F3  1  98               tya                         ; $C1F3: 98
00C1F4  1  2A               rol                         ; $C1F4: 2A
00C1F5  1  85 08            sta $08                     ; $C1F5: 85 08
00C1F7  1               
00C1F7  1  38               sec                         ; $C1F7: 38
00C1F8  1               
00C1F8  1  AD 38 05         lda $0538                   ; $C1F8: AD 38 05
00C1FB  1  E5 07            sbc $07                     ; $C1FB: E5 07
00C1FD  1  8D 38 05         sta $0538                   ; $C1FD: 8D 38 05
00C200  1               
00C200  1  AD 39 05         lda $0539                   ; $C200: AD 39 05
00C203  1  E5 08            sbc $08                     ; $C203: E5 08
00C205  1  8D 39 05         sta $0539                   ; $C205: 8D 39 05
00C208  1               
00C208  1  20 D2 CA         jsr EvaluateTrajectoryResult                   ; $C208: 20 D2 CA
00C20B  1               
00C20B  1               ; ----------------------------------------------------------------------------
00C20B  1               ; Advance state and refresh coordinate-related values.
00C20B  1               ; ----------------------------------------------------------------------------
00C20B  1               
00C20B  1  A5 5D            lda BaseMotionPhase             ; $C20B: A5 5D
00C20D  1  C9 03            cmp #$03                    ; $C20D: C9 03
00C20F  1  B0 04            bcs AdvanceBaseMotionPhase
00C211  1                                               ; $C20F: B0 04
00C211  1               
00C211  1  A9 10            lda #$10                    ; $C211: A9 10
00C213  1  85 FF            sta RenderStateFlags           ; $C213: 85 FF
00C215  1               
00C215  1               AdvanceBaseMotionPhase:      ; $C215
00C215  1  E6 5D            inc BaseMotionPhase             ; $C215: E6 5D
00C217  1               
00C217  1  AD 08 05         lda $0508                   ; $C217: AD 08 05
00C21A  1  0D 39 05         ora $0539                   ; $C21A: 0D 39 05
00C21D  1  0D 6A 05         ora $056A                   ; $C21D: 0D 6A 05
00C220  1  D0 06            bne UpdatePositionSignState            ; $C220: D0 06
00C222  1               
00C222  1  20 43 C9         jsr ClearBaseAccelerationFields            ; $C222: 20 43 C9
00C225  1  20 4F C9         jsr ClearBasePositionFields            ; $C225: 20 4F C9
00C228  1               
00C228  1               ; ----------------------------------------------------------------------------
00C228  1               ; Calculate a signed magnitude from the current position.
00C228  1               ; ----------------------------------------------------------------------------
00C228  1               
00C228  1               UpdatePositionSignState:                   ; $C228
00C228  1  38               sec                         ; $C228: 38
00C229  1               
00C229  1  AD 3B 05         lda $053B                   ; $C229: AD 3B 05
00C22C  1  E9 0A            sbc #$0A                    ; $C22C: E9 0A
00C22E  1  10 0A            bpl SaveSignedPositionDelta  ; $C22E: 10 0A
00C230  1               
00C230  1  AD 0A 05         lda $050A                   ; $C230: AD 0A 05
00C233  1  10 02            bpl SubtractPositionThreshold   ; $C233: 10 02
00C235  1               
00C235  1  49 FF            eor #$FF                    ; $C235: 49 FF
00C237  1               
00C237  1               SubtractPositionThreshold:          ; $C237
00C237  1  38               sec                         ; $C237: 38
00C238  1  E9 0A            sbc #$0A                    ; $C238: E9 0A
00C23A  1               
00C23A  1               SaveSignedPositionDelta:         ; $C23A
00C23A  1  48               pha                         ; $C23A: 48
00C23B  1               
00C23B  1  45 B7            eor PositionSignState       ; $C23B: 45 B7
00C23D  1  10 0A            bpl CommitSignedPositionDelta
00C23F  1                                               ; $C23D: 10 0A
00C23F  1               
00C23F  1  A5 42            lda CurrentObjectArrayOffset        ; $C23F: A5 42
00C241  1  D0 06            bne CommitSignedPositionDelta
00C243  1                                               ; $C241: D0 06
00C243  1               
00C243  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $C243: 20 0A EB
00C246  1               
00C246  1                   ; Inline command data consumed by the routine at QueueInlineObjectEvent.
00C246  1  23 52 C2         .byte $23,$52,$C2           ; $C246-$C248
00C249  1               
00C249  1               CommitSignedPositionDelta:      ; $C249
00C249  1  68               pla                         ; $C249: 68
00C24A  1  85 B7            sta PositionSignState       ; $C24A: 85 B7
00C24C  1               
00C24C  1  0A               asl                         ; $C24C: 0A
00C24D  1  20 46 E7         jsr InitializeRenderingStateFromCarry                   ; $C24D: 20 46 E7
00C250  1               
00C250  1  4C 6A EB         jmp CommonEngineExit                   ; $C250: 4C 6A EB
00C253  1               
00C253  1               ; ----------------------------------------------------------------------------
00C253  1               ; Alternate object/state path.
00C253  1               ; ----------------------------------------------------------------------------
00C253  1               
00C253  1               UpdateAllGameplayObjects:                   ; $C253
00C253  1  A2 26            ldx #$26                    ; $C253: A2 26
00C255  1               
00C255  1               UpdateNextGameplayObject:              ; $C255
00C255  1  86 42            stx CurrentObjectArrayOffset        ; $C255: 86 42
00C257  1  20 B7 E6         jsr ClearMovementTransforms                   ; $C257: 20 B7 E6
00C25A  1               
00C25A  1  A6 42            ldx CurrentObjectArrayOffset        ; $C25A: A6 42
00C25C  1  CA               dex                         ; $C25C: CA
00C25D  1  CA               dex                         ; $C25D: CA
00C25E  1  D0 F5            bne UpdateNextGameplayObject       ; $C25E: D0 F5
00C260  1               
00C260  1  86 42            stx CurrentObjectArrayOffset        ; $C260: 86 42
00C262  1  4C 6A EB         jmp CommonEngineExit                   ; $C262: 4C 6A EB
00C265  1               
00C265  1               ; ============================================================================
00C265  1               ; $C265-$C2DD
00C265  1               ; Select object sprite attributes and animation tiles.
00C265  1               ; ============================================================================
00C265  1               
00C265  1               UpdateBaseObjectSprites:                   ; $C265
00C265  1  A5 5C            lda BaseMotionActive                     ; $C265: A5 5C
00C267  1  F0 67            beq SetDefaultBaseObjectTile
00C269  1                                               ; $C267: F0 67
00C269  1               
00C269  1  A5 FF            lda RenderStateFlags           ; $C269: A5 FF
00C26B  1  AE 6C 05         ldx $056C                   ; $C26B: AE 6C 05
00C26E  1               
00C26E  1  E0 03            cpx #$03                    ; $C26E: E0 03
00C270  1  90 09            bcc SaveBaseObjectRenderFlags  ; $C270: 90 09
00C272  1               
00C272  1  09 20            ora #$20                    ; $C272: 09 20
00C274  1               
00C274  1  AE 6A 05         ldx $056A                   ; $C274: AE 6A 05
00C277  1  10 02            bpl SaveBaseObjectRenderFlags  ; $C277: 10 02
00C279  1               
00C279  1  09 40            ora #$40                    ; $C279: 09 40
00C27B  1               
00C27B  1               SaveBaseObjectRenderFlags:         ; $C27B
00C27B  1  85 FF            sta RenderStateFlags           ; $C27B: 85 FF
00C27D  1               
00C27D  1  20 73 E6         jsr BuildCurrentMovementTransforms                   ; $C27D: 20 73 E6
00C280  1  B0 21            bcs SelectSecondaryAnimationTile
00C282  1                                               ; $C280: B0 21
00C282  1               
00C282  1  9D DD 03         sta $03DD,x                 ; $C282: 9D DD 03
00C285  1               
00C285  1  A5 36            lda ObjectScreenX                     ; $C285: A5 36
00C287  1  9D BB 03         sta $03BB,x                 ; $C287: 9D BB 03
00C28A  1               
00C28A  1               ; ----------------------------------------------------------------------------
00C28A  1               ; Select the first animation tile according to the value in $2E.
00C28A  1               ; ----------------------------------------------------------------------------
00C28A  1               
00C28A  1  A4 2E            ldy $2E                     ; $C28A: A4 2E
00C28C  1               
00C28C  1  A9 76            lda #$76                    ; $C28C: A9 76
00C28E  1  C0 20            cpy #$20                    ; $C28E: C0 20
00C290  1  B0 0E            bcs StorePrimaryAnimationTile
00C292  1                                               ; $C290: B0 0E
00C292  1               
00C292  1  A9 77            lda #$77                    ; $C292: A9 77
00C294  1  C0 12            cpy #$12                    ; $C294: C0 12
00C296  1  B0 08            bcs StorePrimaryAnimationTile
00C298  1                                               ; $C296: B0 08
00C298  1               
00C298  1  A9 78            lda #$78                    ; $C298: A9 78
00C29A  1  C0 08            cpy #$08                    ; $C29A: C0 08
00C29C  1  B0 02            bcs StorePrimaryAnimationTile
00C29E  1                                               ; $C29C: B0 02
00C29E  1               
00C29E  1  A9 79            lda #$79                    ; $C29E: A9 79
00C2A0  1               
00C2A0  1               StorePrimaryAnimationTile:     ; $C2A0
00C2A0  1  9D 99 03         sta $0399,x                 ; $C2A0: 9D 99 03
00C2A3  1               
00C2A3  1               ; ----------------------------------------------------------------------------
00C2A3  1               ; Select the second animation tile.
00C2A3  1               ; ----------------------------------------------------------------------------
00C2A3  1               
00C2A3  1               SelectSecondaryAnimationTile:  ; $C2A3
00C2A3  1  20 95 E6         jsr BuildBaseMovementTransforms                   ; $C2A3: 20 95 E6
00C2A6  1  B0 2F            bcs SetFinalBaseObjectTile
00C2A8  1                                               ; $C2A6: B0 2F
00C2A8  1               
00C2A8  1  A4 2E            ldy $2E                     ; $C2A8: A4 2E
00C2AA  1               
00C2AA  1  A9 7A            lda #$7A                    ; $C2AA: A9 7A
00C2AC  1  C0 20            cpy #$20                    ; $C2AC: C0 20
00C2AE  1  B0 1A            bcs StoreSecondaryAnimationTile
00C2B0  1                                               ; $C2AE: B0 1A
00C2B0  1               
00C2B0  1  A9 71            lda #$71                    ; $C2B0: A9 71
00C2B2  1  C0 12            cpy #$12                    ; $C2B2: C0 12
00C2B4  1  B0 14            bcs StoreSecondaryAnimationTile
00C2B6  1                                               ; $C2B4: B0 14
00C2B6  1               
00C2B6  1  A9 72            lda #$72                    ; $C2B6: A9 72
00C2B8  1  C0 08            cpy #$08                    ; $C2B8: C0 08
00C2BA  1  B0 0E            bcs StoreSecondaryAnimationTile
00C2BC  1                                               ; $C2BA: B0 0E
00C2BC  1               
00C2BC  1  A9 73            lda #$73                    ; $C2BC: A9 73
00C2BE  1  C0 05            cpy #$05                    ; $C2BE: C0 05
00C2C0  1  B0 08            bcs StoreSecondaryAnimationTile
00C2C2  1                                               ; $C2C0: B0 08
00C2C2  1               
00C2C2  1  A9 74            lda #$74                    ; $C2C2: A9 74
00C2C4  1  C0 03            cpy #$03                    ; $C2C4: C0 03
00C2C6  1  B0 02            bcs StoreSecondaryAnimationTile
00C2C8  1                                               ; $C2C6: B0 02
00C2C8  1               
00C2C8  1  A9 75            lda #$75                    ; $C2C8: A9 75
00C2CA  1               
00C2CA  1               StoreSecondaryAnimationTile:    ; $C2CA
00C2CA  1  9D 9A 03         sta $039A,x                 ; $C2CA: 9D 9A 03
00C2CD  1               
00C2CD  1  4C DE C2         jmp BuildFrameOam            ; $C2CD: 4C DE C2
00C2D0  1               
00C2D0  1               ; ----------------------------------------------------------------------------
00C2D0  1               ; Default tile path when $5C is zero.
00C2D0  1               ; ----------------------------------------------------------------------------
00C2D0  1               
00C2D0  1               SetDefaultBaseObjectTile:    ; $C2D0
00C2D0  1  A6 C9            ldx SpriteSortBaseIndex        ; $C2D0: A6 C9
00C2D2  1               
00C2D2  1  A9 7A            lda #$7A                    ; $C2D2: A9 7A
00C2D4  1  9D 9A 03         sta $039A,x                 ; $C2D4: 9D 9A 03
00C2D7  1               
00C2D7  1               SetFinalBaseObjectTile:      ; $C2D7
00C2D7  1  A6 C9            ldx SpriteSortBaseIndex        ; $C2D7: A6 C9
00C2D9  1               
00C2D9  1  A9 7A            lda #$7A                    ; $C2D9: A9 7A
00C2DB  1  9D 9B 03         sta $039B,x                 ; $C2DB: 9D 9B 03
00C2DE  1               
00C2DE  1               ; ============================================================================
00C2DE  1               ; $C2DE-$C330
00C2DE  1               ; Initialize OAM entries for the current game state.
00C2DE  1               ; ============================================================================
00C2DE  1               
00C2DE  1               BuildFrameOam:                   ; $C2DE
00C2DE  1  A5 1D            lda TransitionActive                     ; $C2DE: A5 1D
00C2E0  1  F0 13            beq CheckOamBuildMode  ; $C2E0: F0 13
00C2E2  1               
00C2E2  1               ; ----------------------------------------------------------------------------
00C2E2  1               ; Copy a 88-byte sprite/OAM template from $F94D into shadow OAM at $0200.
00C2E2  1               ; ----------------------------------------------------------------------------
00C2E2  1               
00C2E2  1  A2 00            ldx #$00                    ; $C2E2: A2 00
00C2E4  1  A0 58            ldy #$58                    ; $C2E4: A0 58
00C2E6  1               
00C2E6  1               CopyTransitionOamTemplate:   ; $C2E6
00C2E6  1  BD 4D F9         lda FrameOamTemplate_F94D,x                 ; $C2E6: BD 4D F9
00C2E9  1  9D 00 02         sta $0200,x                 ; $C2E9: 9D 00 02
00C2EC  1               
00C2EC  1  E8               inx                         ; $C2EC: E8
00C2ED  1  88               dey                         ; $C2ED: 88
00C2EE  1  D0 F6            bne CopyTransitionOamTemplate
00C2F0  1                                               ; $C2EE: D0 F6
00C2F0  1               
00C2F0  1  86 3F            stx OamWriteOffset          ; $C2F0: 86 3F
00C2F2  1  4C AA C3         jmp TerminatePpuUpdateQueue
00C2F5  1                                               ; $C2F2: 4C AA C3
00C2F5  1               
00C2F5  1               ; ----------------------------------------------------------------------------
00C2F5  1               ; Alternate path used when $1D is zero.
00C2F5  1               ; ----------------------------------------------------------------------------
00C2F5  1               
00C2F5  1               CheckOamBuildMode:         ; $C2F5
00C2F5  1  A5 44            lda PlayerSelectionActive         ; $C2F5: A5 44
00C2F7  1  F0 40            beq SortObjectsByY          ; $C2F7: F0 40
00C2F9  1               
00C2F9  1               ; ----------------------------------------------------------------------------
00C2F9  1               ; Copy an eight-byte OAM template from $C331 into $0200-$0207.
00C2F9  1               ; The table itself remains in the following .incbin region for now.
00C2F9  1               ; ----------------------------------------------------------------------------
00C2F9  1               
00C2F9  1  A2 07            ldx #$07                    ; $C2F9: A2 07
00C2FB  1               
00C2FB  1               CopySelectionOamTemplate: ; $C2FB
00C2FB  1  BD 31 C3         lda $C331,x                 ; $C2FB: BD 31 C3
00C2FE  1  9D 00 02         sta $0200,x                 ; $C2FE: 9D 00 02
00C301  1               
00C301  1  CA               dex                         ; $C301: CA
00C302  1  10 F7            bpl CopySelectionOamTemplate
00C304  1                                               ; $C302: 10 F7
00C304  1               
00C304  1               ; ----------------------------------------------------------------------------
00C304  1               ; Position the first sprite using the selected player's coordinate.
00C304  1               ; Each value is multiplied by 16 and offset by $50.
00C304  1               ; ----------------------------------------------------------------------------
00C304  1               
00C304  1  A6 4B            ldx ActivePlayerSide            ; $C304: A6 4B
00C306  1               
00C306  1  B5 34            lda PlayerOneSelection,x        ; $C306: B5 34
00C308  1  0A               asl                         ; $C308: 0A
00C309  1  0A               asl                         ; $C309: 0A
00C30A  1  0A               asl                         ; $C30A: 0A
00C30B  1  0A               asl                         ; $C30B: 0A
00C30C  1               
00C30C  1  69 50            adc #$50                    ; $C30C: 69 50
00C30E  1  8D 03 02         sta $0203                   ; $C30E: 8D 03 02
00C311  1               
00C311  1               ; ----------------------------------------------------------------------------
00C311  1               ; Position the second sprite using the opposite player's coordinate.
00C311  1               ; ----------------------------------------------------------------------------
00C311  1               
00C311  1  8A               txa                         ; $C311: 8A
00C312  1  49 01            eor #$01                    ; $C312: 49 01
00C314  1  AA               tax                         ; $C314: AA
00C315  1               
00C315  1  B5 34            lda PlayerOneSelection,x        ; $C315: B5 34
00C317  1  0A               asl                         ; $C317: 0A
00C318  1  0A               asl                         ; $C318: 0A
00C319  1  0A               asl                         ; $C319: 0A
00C31A  1  0A               asl                         ; $C31A: 0A
00C31B  1               
00C31B  1  69 50            adc #$50                    ; $C31B: 69 50
00C31D  1  8D 07 02         sta $0207                   ; $C31D: 8D 07 02
00C320  1               
00C320  1               ; ----------------------------------------------------------------------------
00C320  1               ; Choose the tile used by the second sprite.
00C320  1               ; ----------------------------------------------------------------------------
00C320  1               
00C320  1  A5 40            lda ModeFlags               ; $C320: A5 40
00C322  1  4A               lsr                         ; $C322: 4A
00C323  1  B0 05            bcs FinishSelectionOam     ; $C323: B0 05
00C325  1               
00C325  1  A9 AC            lda #$AC                    ; $C325: A9 AC
00C327  1  8D 05 02         sta $0205                   ; $C327: 8D 05 02
00C32A  1               
00C32A  1               FinishSelectionOam:            ; $C32A
00C32A  1  A2 08            ldx #$08                    ; $C32A: A2 08
00C32C  1  86 3F            stx OamWriteOffset          ; $C32C: 86 3F
00C32E  1               
00C32E  1  4C 86 C3         jmp FinalizeOamAndPpuQueue  ; $C32E: 4C 86 C3
00C331  1               
00C331  1               ; ============================================================================
00C331  1               ; $C331-$C338
00C331  1               ; Eight-byte OAM template referenced by the code at $C2FB.
00C331  1               ; ============================================================================
00C331  1               
00C331  1               OAMTemplate_C331:               ; $C331
00C331  1  77 A2 03 00      .byte $77,$A2,$03,$00       ; $C331-$C334
00C335  1  77 A4 03 00      .byte $77,$A4,$03,$00       ; $C335-$C338
00C339  1               
00C339  1               ; ============================================================================
00C339  1               ; $C339-$C385
00C339  1               ; Sort object indices by their signed 16-bit coordinates, then emit sprite
00C339  1               ; information in the resulting order.
00C339  1               ; ============================================================================
00C339  1               
00C339  1               SortObjectsByY:                   ; $C339
00C339  1  A4 C9            ldy SpriteSortBaseIndex                     ; $C339: A4 C9
00C33B  1               
00C33B  1  C8               iny                         ; $C33B: C8
00C33C  1               
00C33C  1               SortNextObjectPair:          ; $C33C
00C33C  1  84 22            sty $22                     ; $C33C: 84 22
00C33E  1               
00C33E  1  BE 78 03         ldx $0378,y                 ; $C33E: BE 78 03
00C341  1  B9 77 03         lda $0377,y                 ; $C341: B9 77 03
00C344  1  A8               tay                         ; $C344: A8
00C345  1               
00C345  1               ; ----------------------------------------------------------------------------
00C345  1               ; Compare the signed 16-bit values at:
00C345  1               ;
00C345  1               ;   $0538,X / $0539,X
00C345  1               ;   $0538,Y / $0539,Y
00C345  1               ;
00C345  1               ; The subtraction is used only for ordering. If the X entry sorts before the
00C345  1               ; Y entry, their indices in $0377/$0378 are exchanged.
00C345  1               ; ----------------------------------------------------------------------------
00C345  1               
00C345  1  BD 38 05         lda $0538,x                 ; $C345: BD 38 05
00C348  1  D9 38 05         cmp $0538,y                 ; $C348: D9 38 05
00C34B  1               
00C34B  1  BD 39 05         lda $0539,x                 ; $C34B: BD 39 05
00C34E  1  F9 39 05         sbc $0539,y                 ; $C34E: F9 39 05
00C351  1               
00C351  1  10 0A            bpl ContinueObjectDepthSort
00C353  1                                               ; $C351: 10 0A
00C353  1               
00C353  1  98               tya                         ; $C353: 98
00C354  1               
00C354  1  A4 22            ldy $22                     ; $C354: A4 22
00C356  1  99 78 03         sta $0378,y                 ; $C356: 99 78 03
00C359  1               
00C359  1  8A               txa                         ; $C359: 8A
00C35A  1  99 77 03         sta $0377,y                 ; $C35A: 99 77 03
00C35D  1               
00C35D  1               ContinueObjectDepthSort:      ; $C35D
00C35D  1  A4 22            ldy $22                     ; $C35D: A4 22
00C35F  1  C8               iny                         ; $C35F: C8
00C360  1               
00C360  1  C4 CA            cpy $CA                     ; $C360: C4 CA
00C362  1  90 D8            bcc SortNextObjectPair   ; $C362: 90 D8
00C364  1               
00C364  1  A4 C9            ldy SpriteSortBaseIndex                     ; $C364: A4 C9
00C366  1               
00C366  1               RenderNextSortedObject: ; $C366
00C366  1  B9 78 03         lda $0378,y                 ; $C366: B9 78 03
00C369  1  4A               lsr                         ; $C369: 4A
00C36A  1  65 C9            adc SpriteSortBaseIndex                     ; $C36A: 65 C9
00C36C  1  AA               tax                         ; $C36C: AA
00C36D  1               
00C36D  1  BD BC 03         lda $03BC,x                 ; $C36D: BD BC 03
00C370  1  85 36            sta ObjectScreenX                     ; $C370: 85 36
00C372  1               
00C372  1  BD DE 03         lda $03DE,x                 ; $C372: BD DE 03
00C375  1  85 38            sta ObjectScreenY                     ; $C375: 85 38
00C377  1               
00C377  1  BD 9A 03         lda $039A,x                 ; $C377: BD 9A 03
00C37A  1               
00C37A  1  84 22            sty $22                     ; $C37A: 84 22
00C37C  1  20 7B E7         jsr RenderSpriteRecordList                   ; $C37C: 20 7B E7
00C37F  1  A4 22            ldy $22                     ; $C37F: A4 22
00C381  1               
00C381  1  C4 CA            cpy $CA                     ; $C381: C4 CA
00C383  1  C8               iny                         ; $C383: C8
00C384  1  90 E0            bcc RenderNextSortedObject
00C386  1                                               ; $C384: 90 E0
00C386  1               
00C386  1               ; ============================================================================
00C386  1               ; $C386-$C3C9
00C386  1               ; Copy additional OAM entries, terminate the PPU command queue, hide unused
00C386  1               ; sprites, and finish the frame.
00C386  1               ; ============================================================================
00C386  1               
00C386  1               FinalizeOamAndPpuQueue:                   ; $C386
00C386  1  A5 C7            lda ObjectListFlag                     ; $C386: A5 C7
00C388  1  D0 20            bne TerminatePpuUpdateQueue
00C38A  1                                               ; $C388: D0 20
00C38A  1               
00C38A  1               ; ----------------------------------------------------------------------------
00C38A  1               ; Copy twenty bytes from $EBC2 into available shadow OAM space.
00C38A  1               ; ----------------------------------------------------------------------------
00C38A  1               
00C38A  1  A6 3F            ldx OamWriteOffset          ; $C38A: A6 3F
00C38C  1  A0 13            ldy #$13                    ; $C38C: A0 13
00C38E  1               
00C38E  1               CopyStatusOamData:       ; $C38E
00C38E  1  B9 C2 EB         lda $EBC2,y                 ; $C38E: B9 C2 EB
00C391  1  9D 00 02         sta $0200,x                 ; $C391: 9D 00 02
00C394  1               
00C394  1  E8               inx                         ; $C394: E8
00C395  1  88               dey                         ; $C395: 88
00C396  1  10 F6            bpl CopyStatusOamData
00C398  1                                               ; $C396: 10 F6
00C398  1               
00C398  1               ; ----------------------------------------------------------------------------
00C398  1               ; Select two additional bytes from a table beginning at $EBBC.
00C398  1               ; ----------------------------------------------------------------------------
00C398  1               
00C398  1  A4 34            ldy PlayerOneSelection          ; $C398: A4 34
00C39A  1  B9 BC EB         lda $EBBC,y                 ; $C39A: B9 BC EB
00C39D  1  9D F9 01         sta $01F9,x                 ; $C39D: 9D F9 01
00C3A0  1               
00C3A0  1  A4 35            ldy PlayerTwoSelection          ; $C3A0: A4 35
00C3A2  1  B9 BC EB         lda $EBBC,y                 ; $C3A2: B9 BC EB
00C3A5  1  9D FD 01         sta $01FD,x                 ; $C3A5: 9D FD 01
00C3A8  1               
00C3A8  1  86 3F            stx OamWriteOffset          ; $C3A8: 86 3F
00C3AA  1               
00C3AA  1               ; ----------------------------------------------------------------------------
00C3AA  1               ; Terminate the PPU command queue.
00C3AA  1               ; ----------------------------------------------------------------------------
00C3AA  1               
00C3AA  1               TerminatePpuUpdateQueue:    ; $C3AA
00C3AA  1  A9 00            lda #$00                    ; $C3AA: A9 00
00C3AC  1  A4 3E            ldy PpuQueueOffset          ; $C3AC: A4 3E
00C3AE  1  99 00 03         sta $0300,y                 ; $C3AE: 99 00 03
00C3B1  1               
00C3B1  1               ; ----------------------------------------------------------------------------
00C3B1  1               ; Hide all unused sprites by writing $F0 to each remaining OAM Y coordinate.
00C3B1  1               ; ----------------------------------------------------------------------------
00C3B1  1               
00C3B1  1  A6 3F            ldx OamWriteOffset          ; $C3B1: A6 3F
00C3B3  1  D0 04            bne HideUnusedOamSprites
00C3B5  1                                               ; $C3B3: D0 04
00C3B5  1               
00C3B5  1  A5 20            lda FrameState20            ; $C3B5: A5 20
00C3B7  1  D0 0E            bne FinishFrameRendering   ; $C3B7: D0 0E
00C3B9  1               
00C3B9  1               HideUnusedOamSprites:       ; $C3B9
00C3B9  1  A9 F0            lda #$F0                    ; $C3B9: A9 F0
00C3BB  1               
00C3BB  1               HideUnusedOamSpriteLoop:    ; $C3BB
00C3BB  1  9D 00 02         sta $0200,x                 ; $C3BB: 9D 00 02
00C3BE  1               
00C3BE  1  E8               inx                         ; $C3BE: E8
00C3BF  1  E8               inx                         ; $C3BF: E8
00C3C0  1  E8               inx                         ; $C3C0: E8
00C3C1  1  E8               inx                         ; $C3C1: E8
00C3C2  1               
00C3C2  1  D0 F7            bne HideUnusedOamSpriteLoop
00C3C4  1                                               ; $C3C2: D0 F7
00C3C4  1               
00C3C4  1  20 F5 E5         jsr AdvanceRandomState                   ; $C3C4: 20 F5 E5
00C3C7  1               
00C3C7  1               FinishFrameRendering:          ; $C3C7
00C3C7  1  4C 6A EB         jmp CommonEngineExit                   ; $C3C7: 4C 6A EB
00C3CA  1               
00C3CA  1               ; ============================================================================
00C3CA  1               ; $C3CA-$C40A
00C3CA  1               ; Update one object's signed fixed-point position.
00C3CA  1               ;
00C3CA  1               ; Entry:
00C3CA  1               ;   X = object-array offset
00C3CA  1               ;
00C3CA  1               ; Fields used relative to X:
00C3CA  1               ;   $0506,X = fractional movement component
00C3CA  1               ;   $0507,X = position low byte
00C3CA  1               ;   $0508,X = position high byte / signed movement component
00C3CA  1               ;   $0509,X = second position low byte
00C3CA  1               ;   $050A,X = second position high byte
00C3CA  1               ;
00C3CA  1               ; Called earlier with X = $00, $31, and $62.
00C3CA  1               ; ============================================================================
00C3CA  1               
00C3CA  1               ; ----------------------------------------------------------------------------
00C3CA  1               ; Contract:
00C3CA  1               ;   Description: Implements Integrate Object Velocity And Position.
00C3CA  1               ;   Entry: Registers: A, Y; Memory: $0506, $0508, mathtemp05, $0507, $0509, $050a
00C3CA  1               ;   Returns/products: Registers/clobbers: A, Y
00C3CA  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00C3CA  1               ;   Memory effects: mathtemp05, $0507, $0508, $0509, $050a
00C3CA  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00C3CA  1               ;          comparison, load, or store path and are not a stable API product.
00C3CA  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 3.
00C3CA  1               ; ----------------------------------------------------------------------------
00C3CA  1               IntegrateObjectVelocityAndPosition:                   ; $C3CA
00C3CA  1  BC 06 05         ldy $0506,x                 ; $C3CA: BC 06 05
00C3CD  1               
00C3CD  1  BD 08 05         lda $0508,x                 ; $C3CD: BD 08 05
00C3D0  1  10 01            bpl CalculateSignedVelocityDelta     ; $C3D0: 10 01
00C3D2  1               
00C3D2  1  C8               iny                         ; $C3D2: C8
00C3D3  1                                               ; Adjust the high-byte sign value.
00C3D3  1               
00C3D3  1               CalculateSignedVelocityDelta:            ; $C3D3
00C3D3  1  38               sec                         ; $C3D3: 38
00C3D4  1               
00C3D4  1  A9 00            lda #$00                    ; $C3D4: A9 00
00C3D6  1  FD 08 05         sbc $0508,x                 ; $C3D6: FD 08 05
00C3D9  1  B0 01            bcs SaveVelocitySignExtension   ; $C3D9: B0 01
00C3DB  1               
00C3DB  1  88               dey                         ; $C3DB: 88
00C3DC  1               
00C3DC  1               SaveVelocitySignExtension:          ; $C3DC
00C3DC  1  84 05            sty MathTemp05              ; $C3DC: 84 05
00C3DE  1               
00C3DE  1               ; ----------------------------------------------------------------------------
00C3DE  1               ; Arithmetic shift the signed 16-bit value in $05:A right twice.
00C3DE  1               ;
00C3DE  1               ; CMP #$80 places bit 7 of Y into carry:
00C3DE  1               ;   Y >= $80 sets carry
00C3DE  1               ;   Y <  $80 clears carry
00C3DE  1               ;
00C3DE  1               ; ROR $05 followed by ROR A therefore performs a sign-preserving shift.
00C3DE  1               ; ----------------------------------------------------------------------------
00C3DE  1               
00C3DE  1  C0 80            cpy #$80                    ; $C3DE: C0 80
00C3E0  1  66 05            ror MathTemp05              ; $C3E0: 66 05
00C3E2  1  6A               ror                         ; $C3E2: 6A
00C3E3  1               
00C3E3  1  C0 80            cpy #$80                    ; $C3E3: C0 80
00C3E5  1  66 05            ror MathTemp05              ; $C3E5: 66 05
00C3E7  1  6A               ror                         ; $C3E7: 6A
00C3E8  1               
00C3E8  1               ; ----------------------------------------------------------------------------
00C3E8  1               ; Add the shifted signed value to $0507,X/$0508,X.
00C3E8  1               ; ----------------------------------------------------------------------------
00C3E8  1               
00C3E8  1  A4 05            ldy MathTemp05              ; $C3E8: A4 05
00C3EA  1               
00C3EA  1  7D 07 05         adc $0507,x                 ; $C3EA: 7D 07 05
00C3ED  1  9D 07 05         sta $0507,x                 ; $C3ED: 9D 07 05
00C3F0  1               
00C3F0  1  98               tya                         ; $C3F0: 98
00C3F1  1               
00C3F1  1  A0 00            ldy #$00                    ; $C3F1: A0 00
00C3F3  1               
00C3F3  1  7D 08 05         adc $0508,x                 ; $C3F3: 7D 08 05
00C3F6  1  9D 08 05         sta $0508,x                 ; $C3F6: 9D 08 05
00C3F9  1               
00C3F9  1  10 01            bpl AddIntegratedPosition
00C3FB  1                                               ; $C3F9: 10 01
00C3FB  1               
00C3FB  1  88               dey                         ; $C3FB: 88
00C3FC  1                                               ; Sign-extend the high result.
00C3FC  1               
00C3FC  1               ; ----------------------------------------------------------------------------
00C3FC  1               ; Add the resulting signed value to $0509,X/$050A,X.
00C3FC  1               ; ----------------------------------------------------------------------------
00C3FC  1               
00C3FC  1               AddIntegratedPosition: ; $C3FC
00C3FC  1  18               clc                         ; $C3FC: 18
00C3FD  1               
00C3FD  1  7D 09 05         adc $0509,x                 ; $C3FD: 7D 09 05
00C400  1  9D 09 05         sta $0509,x                 ; $C400: 9D 09 05
00C403  1               
00C403  1  98               tya                         ; $C403: 98
00C404  1               
00C404  1  7D 0A 05         adc $050A,x                 ; $C404: 7D 0A 05
00C407  1  9D 0A 05         sta $050A,x                 ; $C407: 9D 0A 05
00C40A  1               
00C40A  1  60               rts                         ; $C40A: 60
00C40B  1               
00C40B  1               ; ============================================================================
00C40B  1               ; $C40B-$C43D
00C40B  1               ; RESET handler
00C40B  1               ;
00C40B  1               ; Initializes the CPU, clears RAM and PPU state, initializes engine systems,
00C40B  1               ; disables APU channels/frame IRQs, and transfers control to $C74A.
00C40B  1               ; ============================================================================
00C40B  1               
00C40B  1               Reset:                          ; $C40B
00C40B  1  78               sei                         ; $C40B: 78
00C40C  1                                               ; Disable maskable interrupts.
00C40C  1               
00C40C  1  D8               cld                         ; $C40C: D8
00C40D  1                                               ; Clear decimal mode.
00C40D  1               
00C40D  1               ; ----------------------------------------------------------------------------
00C40D  1               ; Clear CPU RAM at $0000-$07FF.
00C40D  1               ;
00C40D  1               ; $01 is used as the high byte of the indirect pointer $00/$01.
00C40D  1               ; Each pass clears one 256-byte page. The loop also repeatedly writes zero to
00C40D  1               ; PPUCTRL at $2000.
00C40D  1               ; ----------------------------------------------------------------------------
00C40D  1               
00C40D  1  A9 07            lda #$07                    ; $C40D: A9 07
00C40F  1  85 01            sta IndirectPtrHi           ; $C40F: 85 01
00C411  1               
00C411  1  A0 00            ldy #$00                    ; $C411: A0 00
00C413  1  84 00            sty IndirectPtrLo           ; $C413: 84 00
00C415  1               
00C415  1  98               tya                         ; $C415: 98
00C416  1                                               ; A = $00
00C416  1               
00C416  1               Reset_ClearPageLoop:            ; $C416
00C416  1  91 00            sta (IndirectPtrLo),y       ; $C416: 91 00
00C418  1  8D 00 20         sta PPUCTRL                 ; $C418: 8D 00 20
00C41B  1               
00C41B  1  88               dey                         ; $C41B: 88
00C41C  1  D0 F8            bne Reset_ClearPageLoop     ; $C41C: D0 F8
00C41E  1               
00C41E  1  C6 01            dec IndirectPtrHi           ; $C41E: C6 01
00C420  1  10 F4            bpl Reset_ClearPageLoop     ; $C420: 10 F4
00C422  1               
00C422  1               ; ----------------------------------------------------------------------------
00C422  1               ; Initialize game and PPU-related systems.
00C422  1               ; ----------------------------------------------------------------------------
00C422  1               
00C422  1  20 B1 C7         jsr InitializeSpriteSortTables                   ; $C422: 20 B1 C7
00C425  1  20 6C E9         jsr DisablePpuRendering     ; $C425: 20 6C E9
00C428  1               
00C428  1               ; ----------------------------------------------------------------------------
00C428  1               ; Disable APU channels and inhibit frame-counter IRQ generation.
00C428  1               ; ----------------------------------------------------------------------------
00C428  1               
00C428  1  A2 00            ldx #$00                    ; $C428: A2 00
00C42A  1  8E 15 40         stx APUSTATUS               ; $C42A: 8E 15 40
00C42D  1                                               ; Disable all APU sound channels.
00C42D  1               
00C42D  1  CA               dex                         ; $C42D: CA
00C42E  1                                               ; X = $FF
00C42E  1               
00C42E  1  8E 17 40         stx JOY2                    ; $C42E: 8E 17 40
00C431  1                                               ; Select five-step frame-counter mode and
00C431  1                                               ; inhibit frame IRQ generation.
00C431  1               
00C431  1               ; ----------------------------------------------------------------------------
00C431  1               ; Invoke the routine at $C8BB.
00C431  1               ;; The three bytes immediately following the JSR are inline data interpreted by
00C431  1               ; that routine. They must not be assembled as 6502 instructions.
00C431  1               ; ----------------------------------------------------------------------------
00C431  1               
00C431  1  20 BB C8         jsr ExpandRecordPointerList ; $C431: 20 BB C8
00C434  1               
00C434  1  22 9C EE         .byte $22,$9C,$EE           ; $C434-$C436
00C437  1                                               ; Inline command/parameter data.
00C437  1               
00C437  1               ; ----------------------------------------------------------------------------
00C437  1               ; Set the initial PPU mask shadow value, then enter the main initialization
00C437  1               ; path. This JMP does not return to RESET.
00C437  1               ; ----------------------------------------------------------------------------
00C437  1               
00C437  1  A9 1A            lda #$1A                    ; $C437: A9 1A
00C439  1  85 DE            sta PpuMaskShadow           ; $C439: 85 DE
00C43B  1               
00C43B  1  4C 4A C7         jmp InitializeTitleScreen                   ; $C43B: 4C 4A C7
00C43E  1               
00C43E  1               ; ============================================================================
00C43E  1               ; $C43E
00C43E  1               ; IRQ/BRK handler
00C43E  1               ; ============================================================================
00C43E  1               
00C43E  1               IRQ:                            ; $C43E
00C43E  1  40               rti                         ; $C43E: 40
00C43F  1               
00C43F  1               ; ============================================================================
00C43F  1               ; $C43F-$C488
00C43F  1               ; Display/update loop
00C43F  1               ; ============================================================================
00C43F  1               
00C43F  1               RunAttractMessageLoop:                   ; $C43F
00C43F  1  A9 00            lda #$00                    ; $C43F: A9 00
00C441  1  85 1F            sta NmiStateFlag            ; $C441: 85 1F
00C443  1               
00C443  1  20 48 EB         jsr SelectObjectEventBank1                   ; $C443: 20 48 EB
00C446  1               
00C446  1               ; ----------------------------------------------------------------------------
00C446  1               ; Draw six blank characters.
00C446  1               ; The routine at $EA17 consumes the inline bytes following the JSR.
00C446  1               ; ----------------------------------------------------------------------------
00C446  1               
00C446  1  A5 C7            lda ObjectListFlag                     ; $C446: A5 C7
00C448  1  18               clc                         ; $C448: 18
00C449  1  09 23            ora #$23                    ; $C449: 09 23
00C44B  1               
00C44B  1  A2 37            ldx #$37                    ; $C44B: A2 37
00C44D  1  A0 06            ldy #$06                    ; $C44D: A0 06
00C44F  1               
00C44F  1  20 17 EA         jsr CopyInlineDisplayRecord                   ; $C44F: 20 17 EA
00C452  1               
00C452  1  06               .byte $06                   ; $C452
00C453  1  25 25 25         .byte $25,$25,$25           ; $C453-$C455
00C456  1  25 25 25         .byte $25,$25,$25           ; $C456-$C458
00C459  1               
00C459  1               ; ----------------------------------------------------------------------------
00C459  1               ; Wait or process an engine command.
00C459  1               ; ----------------------------------------------------------------------------
00C459  1               
00C459  1  A2 0B            ldx #$0B                    ; $C459: A2 0B
00C45B  1  20 4E EB         jsr UpdateObjectEventBank_Exchange                   ; $C45B: 20 4E EB
00C45E  1               
00C45E  1  20 48 EB         jsr SelectObjectEventBank1                   ; $C45E: 20 48 EB
00C461  1               
00C461  1  A9 10            lda #$10                    ; $C461: A9 10
00C463  1  85 FD            sta $FD                     ; $C463: 85 FD
00C465  1               
00C465  1               ; ----------------------------------------------------------------------------
00C465  1               ; Draw the second six-character encoded message.
00C465  1               ; ----------------------------------------------------------------------------
00C465  1               
00C465  1  A5 C7            lda ObjectListFlag          ; $C465: A5 C7
00C467  1  18               clc                         ; $C467: 18
00C468  1  09 23            ora #$23                    ; $C468: 09 23
00C46A  1               
00C46A  1  A2 37            ldx #$37                    ; $C46A: A2 37
00C46C  1  A0 06            ldy #$06                    ; $C46C: A0 06
00C46E  1               
00C46E  1  20 17 EA         jsr CopyInlineDisplayRecord                   ; $C46E: 20 17 EA
00C471  1               
00C471  1  06               .byte $06                   ; $C471
00C472  1  19 0A 1E         .byte $19,$0A,$1E           ; $C472-$C474
00C475  1  1C 0E 25         .byte $1C,$0E,$25           ; $C475-$C477
00C478  1               
00C478  1               ; ----------------------------------------------------------------------------
00C478  1               ; Complete the update, increment $1F, and repeat.
00C478  1               ; ----------------------------------------------------------------------------
00C478  1               
00C478  1  20 48 EB         jsr SelectObjectEventBank1                   ; $C478: 20 48 EB
00C47B  1               
00C47B  1  E6 1F            inc NmiStateFlag            ; $C47B: E6 1F
00C47D  1               
00C47D  1  A2 0B            ldx #$0B                    ; $C47D: A2 0B
00C47F  1  20 4E EB         jsr UpdateObjectEventBank_Exchange                   ; $C47F: 20 4E EB
00C482  1               
00C482  1  A9 10            lda #$10                    ; $C482: A9 10
00C484  1  85 FD            sta $FD                     ; $C484: 85 FD
00C486  1               
00C486  1  4C 3F C4         jmp RunAttractMessageLoop            ; $C486: 4C 3F C4
00C489  1               
00C489  1               ; ============================================================================
00C489  1               ; $C489-$C4B8
00C489  1               ; Wait for controller input, initialize game state, and configure the PPU.
00C489  1               ; ============================================================================
00C489  1               
00C489  1               WaitForStartInput:                   ; $C489
00C489  1  20 4C EB         jsr SelectObjectEventBank0                   ; $C489: 20 4C EB
00C48C  1               
00C48C  1  A5 15            lda ControllerPressed1                     ; $C48C: A5 15
00C48E  1  0A               asl                         ; $C48E: 0A
00C48F  1  0A               asl                         ; $C48F: 0A
00C490  1  0A               asl                         ; $C490: 0A
00C491  1               
00C491  1  90 03            bcc CheckStartInputSign  ; $C491: 90 03
00C493  1               
00C493  1  4C 4A C7         jmp InitializeTitleScreen                   ; $C493: 4C 4A C7
00C496  1               
00C496  1               CheckStartInputSign:         ; $C496
00C496  1  10 F1            bpl WaitForStartInput            ; $C496: 10 F1
00C498  1               
00C498  1               ; ----------------------------------------------------------------------------
00C498  1               ; Initialize state variables.
00C498  1               ; ----------------------------------------------------------------------------
00C498  1               
00C498  1  A9 00            lda #$00                    ; $C498: A9 00
00C49A  1  85 EF            sta GameplaySuspended                     ; $C49A: 85 EF
00C49C  1               
00C49C  1               InitializeNewSession:                   ; $C49C
00C49C  1  A9 00            lda #$00                    ; $C49C: A9 00
00C49E  1  85 60            sta PendingStateTransition                     ; $C49E: 85 60
00C4A0  1  8D 96 05         sta $0596                   ; $C4A0: 8D 96 05
00C4A3  1  85 33            sta RoundStateIndex                     ; $C4A3: 85 33
00C4A5  1               
00C4A5  1  E6 1E            inc SessionActive                     ; $C4A5: E6 1E
00C4A7  1               
00C4A7  1  20 9D EB         jsr InitializeQueuedEventSystem                   ; $C4A7: 20 9D EB
00C4AA  1               
00C4AA  1               ; ----------------------------------------------------------------------------
00C4AA  1               ; Set the PPUCTRL shadow value and initialize PPU-related state.
00C4AA  1               ; ----------------------------------------------------------------------------
00C4AA  1               InitializeSessionDisplay:
00C4AA  1  A9 88            lda #$88                    ; $C4AA: A9 88
00C4AC  1  85 DD            sta PpuCtrlShadow                     ; $C4AC: 85 DD
00C4AE  1               
00C4AE  1  20 6C E9         jsr DisablePpuRendering     ; $C4AE: 20 6C E9
00C4B1  1  20 83 E9         jsr FillPpuMemoryWith26                   ; $C4B1: 20 83 E9
00C4B4  1               
00C4B4  1               ; ----------------------------------------------------------------------------
00C4B4  1               ; The routine at $EA63 consumes the two inline bytes following the JSR.
00C4B4  1               ; They must remain raw data rather than being decoded as 6502 opcodes.
00C4B4  1               ; ----------------------------------------------------------------------------
00C4B4  1               
00C4B4  1  20 63 EA         jsr ProcessInlinePpuStream                   ; $C4B4: 20 63 EA
00C4B7  1               
00C4B7  1  F2 F4            .byte $F2,$F4               ; $C4B7-$C4B8
00C4B9  1                                               ; Inline command/pointer data.
00C4B9  1               
00C4B9  1               ; ============================================================================
00C4B9  1               ; $C4B9-$C51D
00C4B9  1               ; Initialize play state, choose player values, and invoke setup routines.
00C4B9  1               ; ============================================================================
00C4B9  1               
00C4B9  1               InitializeMatchState:                   ; $C4B9
00C4B9  1  20 4F C9         jsr ClearBasePositionFields            ; $C4B9: 20 4F C9
00C4BC  1  20 43 C9         jsr ClearBaseAccelerationFields            ; $C4BC: 20 43 C9
00C4BF  1               
00C4BF  1               ; ----------------------------------------------------------------------------
00C4BF  1               ; Initialize signed position/state values.
00C4BF  1               ; ----------------------------------------------------------------------------
00C4BF  1               
00C4BF  1  A9 80            lda #$80                    ; $C4BF: A9 80
00C4C1  1  8D 3B 05         sta $053B                   ; $C4C1: 8D 3B 05
00C4C4  1  85 B7            sta PositionSignState                     ; $C4C4: 85 B7
00C4C6  1               
00C4C6  1  20 78 E9         jsr EnableNmiAndWaitForFrame                   ; $C4C6: 20 78 E9
00C4C9  1               
00C4C9  1               ; ----------------------------------------------------------------------------
00C4C9  1               ; Obtain two different values from $C850.
00C4C9  1               ; The first is saved in $34 and the second in $35.
00C4C9  1               ; ----------------------------------------------------------------------------
00C4C9  1               
00C4C9  1  20 50 C8         jsr Random0To5                   ; $C4C9: 20 50 C8
00C4CC  1  85 34            sta PlayerOneSelection                     ; $C4CC: 85 34
00C4CE  1               
00C4CE  1               SelectDistinctSecondPlayerValue: ; $C4CE
00C4CE  1  20 50 C8         jsr Random0To5                   ; $C4CE: 20 50 C8
00C4D1  1  C5 34            cmp PlayerOneSelection                     ; $C4D1: C5 34
00C4D3  1  F0 F9            beq SelectDistinctSecondPlayerValue
00C4D5  1                                               ; $C4D3: F0 F9
00C4D5  1               
00C4D5  1  85 35            sta PlayerTwoSelection                     ; $C4D5: 85 35
00C4D7  1               
00C4D7  1               ; ----------------------------------------------------------------------------
00C4D7  1               ; If $EF is nonzero, skip the player/control selection logic.
00C4D7  1               ; ----------------------------------------------------------------------------
00C4D7  1               
00C4D7  1  A5 EF            lda GameplaySuspended                     ; $C4D7: A5 EF
00C4D9  1  D0 31            bne CompleteMatchSetup   ; $C4D9: D0 31
00C4DB  1               
00C4DB  1  A5 40            lda ModeFlags                     ; $C4DB: A5 40
00C4DD  1  29 01            and #$01                    ; $C4DD: 29 01
00C4DF  1  85 43            sta $43                     ; $C4DF: 85 43
00C4E1  1               
00C4E1  1  D0 09            bne DeriveSelectedSideFromMode
00C4E3  1                                               ; $C4E1: D0 09
00C4E3  1               
00C4E3  1               ; ----------------------------------------------------------------------------
00C4E3  1               ; Choose a random low-bit value for $4B.
00C4E3  1               ; ----------------------------------------------------------------------------
00C4E3  1               
00C4E3  1  20 F5 E5         jsr AdvanceRandomState                   ; $C4E3: 20 F5 E5
00C4E6  1  29 01            and #$01                    ; $C4E6: 29 01
00C4E8  1  85 4B            sta ActivePlayerSide                     ; $C4E8: 85 4B
00C4EA  1               
00C4EA  1  10 09            bpl StartPlayerSelection ; $C4EA: 10 09
00C4EC  1                                               ; Always taken after AND #$01.
00C4EC  1               
00C4EC  1               ; ----------------------------------------------------------------------------
00C4EC  1               ; Derive $4B from $43 when $43 is nonzero.
00C4EC  1               ; ----------------------------------------------------------------------------
00C4EC  1               
00C4EC  1               DeriveSelectedSideFromMode:   ; $C4EC
00C4EC  1  4A               lsr                         ; $C4EC: 4A
00C4ED  1  85 4B            sta ActivePlayerSide                     ; $C4ED: 85 4B
00C4EF  1               
00C4EF  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $C4EF: 20 0A EB
00C4F2  1               
00C4F2  1                   ; Inline command data consumed by QueueInlineObjectEvent.
00C4F2  1  03 19 C8         .byte $03,$19,$C8           ; $C4F2-$C4F4
00C4F5  1               
00C4F5  1               StartPlayerSelection:        ; $C4F5
00C4F5  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $C4F5: 20 0A EB
00C4F8  1               
00C4F8  1                   ; Inline command data consumed by QueueInlineObjectEvent.
00C4F8  1  02 19 C8         .byte $02,$19,$C8           ; $C4F8-$C4FA
00C4FB  1               
00C4FB  1  A9 01            lda #$01                    ; $C4FB: A9 01
00C4FD  1  85 44            sta PlayerSelectionActive                     ; $C4FD: 85 44
00C4FF  1               
00C4FF  1               ; ----------------------------------------------------------------------------
00C4FF  1               ; Wait while $43 remains nonnegative.
00C4FF  1               ;
00C4FF  1               ; $EB48 presumably updates asynchronous state, including $43.
00C4FF  1               ; ----------------------------------------------------------------------------
00C4FF  1               
00C4FF  1               WaitForPlayerSelection:      ; $C4FF
00C4FF  1  20 48 EB         jsr SelectObjectEventBank1                   ; $C4FF: 20 48 EB
00C502  1               
00C502  1  A5 43            lda $43                     ; $C502: A5 43
00C504  1  10 F9            bpl WaitForPlayerSelection
00C506  1                                               ; $C504: 10 F9
00C506  1               
00C506  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $C506: 20 0A EB
00C509  1               
00C509  1                   ; Inline command data consumed by QueueInlineObjectEvent.
00C509  1  03 3E C4         .byte $03,$3E,$C4           ; $C509-$C50B
00C50C  1               
00C50C  1               ; ----------------------------------------------------------------------------
00C50C  1               ; Run the main setup sequence.
00C50C  1               ; ----------------------------------------------------------------------------
00C50C  1               
00C50C  1               CompleteMatchSetup:          ; $C50C
00C50C  1  20 5A C8         jsr FillSelectionBackgroundBlocks                   ; $C50C: 20 5A C8
00C50F  1  20 DD C7         jsr QueuePlayerSelectionDisplay                   ; $C50F: 20 DD C7
00C512  1  20 E8 C8         jsr InitializeRandomBitfields                   ; $C512: 20 E8 C8
00C515  1  20 8B CF         jsr QueuePlayerValueDisplay                   ; $C515: 20 8B CF
00C518  1               
00C518  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $C518: 20 0A EB
00C51B  1               
00C51B  1                   ; Inline command data consumed by QueueInlineObjectEvent.
00C51B  1  09 37 CE         .byte $09,$37,$CE           ; $C51B-$C51D
00C51E  1               
00C51E  1               ; ============================================================================
00C51E  1               ; $C51E-$C57E
00C51E  1               ; Conditional state initialization and message display.
00C51E  1               ; ============================================================================
00C51E  1               
00C51E  1               InitializeRoundState:                   ; $C51E
00C51E  1  A5 EF            lda GameplaySuspended                     ; $C51E: A5 EF
00C520  1  F0 08            beq EnableRoundAudio
00C522  1                                               ; $C520: F0 08
00C522  1               
00C522  1  A5 33            lda RoundStateIndex                     ; $C522: A5 33
00C524  1  C9 12            cmp #$12                    ; $C524: C9 12
00C526  1  90 3E            bcc SelectRoundMusicCue
00C528  1                                               ; $C526: 90 3E
00C528  1               
00C528  1  B0 0C            bcs ResetRoundCounters ; $C528: B0 0C
00C52A  1                                               ; Effectively unconditional because either
00C52A  1                                               ; CMP result not taken by BCC has carry set.
00C52A  1               
00C52A  1               ; ----------------------------------------------------------------------------
00C52A  1               ; Configure the APU and initialize a delay value.
00C52A  1               ; ----------------------------------------------------------------------------
00C52A  1               
00C52A  1               EnableRoundAudio:   ; $C52A
00C52A  1  A9 0F            lda #$0F                    ; $C52A: A9 0F
00C52C  1  8D 00 01         sta $0100                   ; $C52C: 8D 00 01
00C52F  1  8D 15 40         sta $4015                   ; $C52F: 8D 15 40
00C532  1                                               ; Enable the four standard APU channels.
00C532  1               
00C532  1  A9 08            lda #$08                    ; $C532: A9 08
00C534  1  85 FD            sta $FD                     ; $C534: 85 FD
00C536  1               
00C536  1               ; ----------------------------------------------------------------------------
00C536  1               ; Clear game-state values and call the setup routine at $D06B.
00C536  1               ; A is zero after TXA.
00C536  1               ; ----------------------------------------------------------------------------
00C536  1               
00C536  1               ResetRoundCounters:        ; $C536
00C536  1  A2 00            ldx #$00                    ; $C536: A2 00
00C538  1               
00C538  1  86 67            stx PlayerOneScore                     ; $C538: 86 67
00C53A  1  86 68            stx PlayerTwoScore                     ; $C53A: 86 68
00C53C  1  86 33            stx RoundStateIndex                     ; $C53C: 86 33
00C53E  1               
00C53E  1  8A               txa                         ; $C53E: 8A
00C53F  1  20 6B D0         jsr InitializeObjectsFromTable                   ; $C53F: 20 6B D0
00C542  1               
00C542  1               ; ----------------------------------------------------------------------------
00C542  1               ; Initialize position/state values and wait for $3C frames or ticks.
00C542  1               ; ----------------------------------------------------------------------------
00C542  1               
00C542  1  A9 80            lda #$80                    ; $C542: A9 80
00C544  1  8D 3B 05         sta $053B                   ; $C544: 8D 3B 05
00C547  1  85 B7            sta PositionSignState                     ; $C547: 85 B7
00C549  1               
00C549  1  A9 3C            lda #$3C                    ; $C549: A9 3C
00C54B  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $C54B: 20 41 EB
00C54E  1               
00C54E  1               ; ----------------------------------------------------------------------------
00C54E  1               ; Draw an eight-character encoded message.
00C54E  1               ;
00C54E  1               ; The routine at $EA17 consumes the inline bytes immediately following
00C54E  1               ; the JSR. The first byte is the character count.
00C54E  1               ; ----------------------------------------------------------------------------
00C54E  1               
00C54E  1  18               clc                         ; $C54E: 18
00C54F  1               
00C54F  1  A9 20            lda #$20                    ; $C54F: A9 20
00C551  1  A2 EC            ldx #$EC                    ; $C551: A2 EC
00C553  1  A0 08            ldy #$08                    ; $C553: A0 08
00C555  1               
00C555  1  20 17 EA         jsr CopyInlineDisplayRecord                   ; $C555: 20 17 EA
00C558  1               
00C558  1  08               .byte $08                   ; $C558: character count
00C559  1  19 15 0A 22      .byte $19,$15,$0A,$22       ; $C559-$C55C
00C55D  1  0B 0A 15 15      .byte $0B,$0A,$15,$15       ; $C55D-$C560
00C561  1               
00C561  1               ; ----------------------------------------------------------------------------
00C561  1               ; Wait for another $3C frames or ticks.
00C561  1               ; ----------------------------------------------------------------------------
00C561  1               
00C561  1  A9 3C            lda #$3C                    ; $C561: A9 3C
00C563  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $C563: 20 41 EB
00C566  1               
00C566  1               ; ----------------------------------------------------------------------------
00C566  1               ; Select a delay or mode value in $FD from the current value of $33.
00C566  1               ; ----------------------------------------------------------------------------
00C566  1               
00C566  1               SelectRoundMusicCue:       ; $C566
00C566  1  A5 33            lda RoundStateIndex                     ; $C566: A5 33
00C568  1  F0 09            beq PrepareRoundObjects   ; $C568: F0 09
00C56A  1               
00C56A  1  A2 20            ldx #$20                    ; $C56A: A2 20
00C56C  1               
00C56C  1  4A               lsr                         ; $C56C: 4A
00C56D  1  90 02            bcc StoreRoundMusicCue  ; $C56D: 90 02
00C56F  1               
00C56F  1  A2 40            ldx #$40                    ; $C56F: A2 40
00C571  1               
00C571  1               StoreRoundMusicCue:         ; $C571
00C571  1  86 FD            stx $FD                     ; $C571: 86 FD
00C573  1               
00C573  1               ; ----------------------------------------------------------------------------
00C573  1               ; Continue engine initialization.
00C573  1               ; ----------------------------------------------------------------------------
00C573  1               
00C573  1               PrepareRoundObjects:          ; $C573
00C573  1  20 DD C7         jsr QueuePlayerSelectionDisplay                   ; $C573: 20 DD C7
00C576  1  20 04 C9         jsr QueueRandomStateRecord                   ; $C576: 20 04 C9
00C579  1               
00C579  1  A2 00            ldx #$00                    ; $C579: A2 00
00C57B  1  86 45            stx MatchCompleteFlag                     ; $C57B: 86 45
00C57D  1  86 64            stx SecondarySequenceState                     ; $C57D: 86 64
00C57F  1               
00C57F  1               ; ============================================================================
00C57F  1               ; $C57F-$C5FD
00C57F  1               ; Clear gameplay state, initialize object data, and prepare the next state.
00C57F  1               ;
00C57F  1               ; Entry:
00C57F  1               ;   X = $00 from the preceding block at $C579.
00C57F  1               ; ============================================================================
00C57F  1               
00C57F  1               ResetGameplayState:    ; $C57F
00C57F  1  86 66            stx InningOrSharedScore                     ; $C57F: 86 66
00C581  1  86 5C            stx BaseMotionActive                     ; $C581: 86 5C
00C583  1               
00C583  1  CA               dex                         ; $C583: CA
00C584  1                                               ; X = $FF
00C584  1               
00C584  1               ; ----------------------------------------------------------------------------
00C584  1               ; Mark four state entries as inactive using $FF.
00C584  1               ; ----------------------------------------------------------------------------
00C584  1               
00C584  1  8E 98 05         stx $0598                   ; $C584: 8E 98 05
00C587  1  8E 99 05         stx $0599                   ; $C587: 8E 99 05
00C58A  1  8E 9A 05         stx $059A                   ; $C58A: 8E 9A 05
00C58D  1  8E 9B 05         stx $059B                   ; $C58D: 8E 9B 05
00C590  1               
00C590  1               ; ----------------------------------------------------------------------------
00C590  1               ; Initialize additional game-state structures.
00C590  1               ; ----------------------------------------------------------------------------
00C590  1               
00C590  1  20 67 CF         jsr QueueRoundNumberDisplay                   ; $C590: 20 67 CF
00C593  1               
00C593  1  A9 00            lda #$00                    ; $C593: A9 00
00C595  1  20 6B D0         jsr InitializeObjectsFromTable                   ; $C595: 20 6B D0
00C598  1               
00C598  1               ; ----------------------------------------------------------------------------
00C598  1               ; Initialize signed position/state values.
00C598  1               ; ----------------------------------------------------------------------------
00C598  1               
00C598  1  A9 80            lda #$80                    ; $C598: A9 80
00C59A  1  8D 3B 05         sta $053B                   ; $C59A: 8D 3B 05
00C59D  1  85 B7            sta PositionSignState                     ; $C59D: 85 B7
00C59F  1               
00C59F  1               ; ----------------------------------------------------------------------------
00C59F  1               ; Wait for or process $B4 ticks.
00C59F  1               ; ----------------------------------------------------------------------------
00C59F  1               
00C59F  1  A9 B4            lda #$B4                    ; $C59F: A9 B4
00C5A1  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $C5A1: 20 41 EB
00C5A4  1               
00C5A4  1               ; ----------------------------------------------------------------------------
00C5A4  1               ; Contract:
00C5A4  1               ;   Description: Internal round-setup continuation at random-direction initialization.
00C5A4  1               ;   Entry: Parent routine state already initialized.
00C5A4  1               ;   Returns/products: Continues round setup; no independent return contract.
00C5A4  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00C5A4  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00C5A4  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00C5A4  1               ;          comparison, load, or store path and are not a stable API product.
00C5A4  1               ;   Validation: Internal-entry contract; call sites: internal entry.
00C5A4  1               ; ----------------------------------------------------------------------------
00C5A4  1               ResumeRoundSetupAtRandomDirection:
00C5A4  1  20 1B C9         jsr QueueRandomDirectionRecord                   ; $C5A4: 20 1B C9
00C5A7  1               
00C5A7  1               ; ----------------------------------------------------------------------------
00C5A7  1               ; Clear two state variables and initialize $46 to one.
00C5A7  1               ; ----------------------------------------------------------------------------
00C5A7  1               
00C5A7  1  A2 00            ldx #$00                    ; $C5A7: A2 00
00C5A9  1               
00C5A9  1  86 62            stx PrimarySequenceState                     ; $C5A9: 86 62
00C5AB  1  86 63            stx TransitionSequenceState                     ; $C5AB: 86 63
00C5AD  1               
00C5AD  1  E8               inx                         ; $C5AD: E8
00C5AE  1                                               ; X = $01
00C5AE  1               
00C5AE  1  86 46            stx StateSequenceActive                     ; $C5AE: 86 46
00C5B0  1               
00C5B0  1               ; ----------------------------------------------------------------------------
00C5B0  1               ; Invoke $CF51 with two different values.
00C5B0  1               ; ----------------------------------------------------------------------------
00C5B0  1               
00C5B0  1  A9 03            lda #$03                    ; $C5B0: A9 03
00C5B2  1  20 51 CF         jsr ClearStateFieldPair                   ; $C5B2: 20 51 CF
00C5B5  1               
00C5B5  1  A9 23            lda #$23                    ; $C5B5: A9 23
00C5B7  1  20 51 CF         jsr ClearStateFieldPair                   ; $C5B7: 20 51 CF
00C5BA  1               
00C5BA  1               ; ----------------------------------------------------------------------------
00C5BA  1               ; Contract:
00C5BA  1               ;   Description: Internal round-setup continuation at selection-display initialization.
00C5BA  1               ;   Entry: Parent routine state already initialized.
00C5BA  1               ;   Returns/products: Continues round setup; no independent return contract.
00C5BA  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00C5BA  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00C5BA  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00C5BA  1               ;          comparison, load, or store path and are not a stable API product.
00C5BA  1               ;   Validation: Internal-entry contract; call sites: internal entry.
00C5BA  1               ; ----------------------------------------------------------------------------
00C5BA  1               ResumeRoundSetupAtSelectionDisplay:
00C5BA  1  20 C9 C7         jsr ClearEightCharacterField                   ; $C5BA: 20 C9 C7
00C5BD  1               
00C5BD  1               ; ----------------------------------------------------------------------------
00C5BD  1               ; Clear individual state entries.
00C5BD  1               ; ----------------------------------------------------------------------------
00C5BD  1               
00C5BD  1  A9 00            lda #$00                    ; $C5BD: A9 00
00C5BF  1               
00C5BF  1  8D 97 05         sta $0597                   ; $C5BF: 8D 97 05
00C5C2  1               
00C5C2  1  8D 9C 05         sta $059C                   ; $C5C2: 8D 9C 05
00C5C5  1  8D 9D 05         sta $059D                   ; $C5C5: 8D 9D 05
00C5C8  1  8D 9E 05         sta $059E                   ; $C5C8: 8D 9E 05
00C5CB  1  8D 9F 05         sta $059F                   ; $C5CB: 8D 9F 05
00C5CE  1  8D A0 05         sta $05A0                   ; $C5CE: 8D A0 05
00C5D1  1               
00C5D1  1  8D A4 05         sta $05A4                   ; $C5D1: 8D A4 05
00C5D4  1  8D A5 05         sta $05A5                   ; $C5D4: 8D A5 05
00C5D7  1  8D A6 05         sta $05A6                   ; $C5D7: 8D A6 05
00C5DA  1               
00C5DA  1               ; ----------------------------------------------------------------------------
00C5DA  1               ; Clear the 38-byte range $056F-$0594.
00C5DA  1               ;
00C5DA  1               ; X counts from $25 down through $00.
00C5DA  1               ; ----------------------------------------------------------------------------
00C5DA  1               
00C5DA  1  A2 25            ldx #$25                    ; $C5DA: A2 25
00C5DC  1               
00C5DC  1               ClearObjectMotionFields:  ; $C5DC
00C5DC  1  9D 6F 05         sta $056F,x                 ; $C5DC: 9D 6F 05
00C5DF  1               
00C5DF  1  CA               dex                         ; $C5DF: CA
00C5E0  1  10 FA            bpl ClearObjectMotionFields
00C5E2  1                                               ; $C5E0: 10 FA
00C5E2  1               
00C5E2  1               ; ----------------------------------------------------------------------------
00C5E2  1               ; Conditional transition based on $33 and the comparison of $67 with $68.
00C5E2  1               ; ----------------------------------------------------------------------------
00C5E2  1               
00C5E2  1  A5 33            lda RoundStateIndex                     ; $C5E2: A5 33
00C5E4  1  C9 11            cmp #$11                    ; $C5E4: C9 11
00C5E6  1  D0 09            bne FinishGameplayReset   ; $C5E6: D0 09
00C5E8  1               
00C5E8  1  A5 67            lda PlayerOneScore                     ; $C5E8: A5 67
00C5EA  1  C5 68            cmp PlayerTwoScore                     ; $C5EA: C5 68
00C5EC  1  B0 03            bcs FinishGameplayReset   ; $C5EC: B0 03
00C5EE  1               
00C5EE  1  4C F7 C6         jmp CompleteMatchState                   ; $C5EE: 4C F7 C6
00C5F1  1               
00C5F1  1               ; ----------------------------------------------------------------------------
00C5F1  1               ; Complete initialization and synchronize with the frame/update system.
00C5F1  1               ; ----------------------------------------------------------------------------
00C5F1  1               
00C5F1  1               FinishGameplayReset:          ; $C5F1
00C5F1  1  20 69 D0         jsr InitializeDefaultObjects                   ; $C5F1: 20 69 D0
00C5F4  1               
00C5F4  1  A9 00            lda #$00                    ; $C5F4: A9 00
00C5F6  1  8D 3B 05         sta $053B                   ; $C5F6: 8D 3B 05
00C5F9  1  85 B7            sta PositionSignState                     ; $C5F9: 85 B7
00C5FB  1               
00C5FB  1  20 48 EB         jsr SelectObjectEventBank1                   ; $C5FB: 20 48 EB
00C5FE  1               
00C5FE  1               ; ============================================================================
00C5FE  1               ; $C5FE-$C6E0
00C5FE  1               ; Main state initialization and processing loop
00C5FE  1               ; ============================================================================
00C5FE  1               
00C5FE  1               RunRoundStateLoop:     ; $C5FE
00C5FE  1  A4 60            ldy PendingStateTransition                     ; $C5FE: A4 60
00C600  1  F0 03            beq CheckRoundTransitionState ; $C600: F0 03
00C602  1               
00C602  1  20 A2 C8         jsr InitializeObjectStateLookup                   ; $C602: 20 A2 C8
00C605  1               
00C605  1               ; ----------------------------------------------------------------------------
00C605  1               ; Dispatch state-specific handlers when either $60 or $46 is nonzero.
00C605  1               ; ----------------------------------------------------------------------------
00C605  1               
00C605  1               CheckRoundTransitionState:        ; $C605
00C605  1  A5 60            lda PendingStateTransition                     ; $C605: A5 60
00C607  1  05 46            ora StateSequenceActive                     ; $C607: 05 46
00C609  1  F0 0E            beq RunPrimaryRoundHandlers
00C60B  1                                               ; $C609: F0 0E
00C60B  1               
00C60B  1  46 46            lsr StateSequenceActive                     ; $C60B: 46 46
00C60D  1               
00C60D  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $C60D: 20 0A EB
00C610  1               
00C610  1                   ; Inline command record consumed by QueueInlineObjectEvent.
00C610  1  0D 77 D4         .byte $0D,$77,$D4           ; $C610-$C612
00C613  1               
00C613  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $C613: 20 0A EB
00C616  1               
00C616  1                   ; Inline command record consumed by QueueInlineObjectEvent.
00C616  1  0F 81 D3         .byte $0F,$81,$D3           ; $C616-$C618
00C619  1               
00C619  1               ; ----------------------------------------------------------------------------
00C619  1               ; Run the primary state handlers.
00C619  1               ; ----------------------------------------------------------------------------
00C619  1               
00C619  1               RunPrimaryRoundHandlers:  ; $C619
00C619  1  20 10 D6         jsr InitializeSecondaryActors                   ; $C619: 20 10 D6
00C61C  1  20 26 D1         jsr InitializeConditionalObject                   ; $C61C: 20 26 D1
00C61F  1               
00C61F  1               ; ----------------------------------------------------------------------------
00C61F  1               ; Clear working state.
00C61F  1               ; ----------------------------------------------------------------------------
00C61F  1               
00C61F  1  A2 00            ldx #$00                    ; $C61F: A2 00
00C621  1               
00C621  1  86 65            stx PendingScoreIncrement                     ; $C621: 86 65
00C623  1  86 5D            stx BaseMotionPhase                     ; $C623: 86 5D
00C625  1  86 5E            stx BaseMotionEventCount                     ; $C625: 86 5E
00C627  1  86 5F            stx TrajectoryResult                     ; $C627: 86 5F
00C629  1  86 60            stx PendingStateTransition                     ; $C629: 86 60
00C62B  1  86 6D            stx SpecialSequenceState                     ; $C62B: 86 6D
00C62D  1  86 6E            stx ObjectTransitionState                     ; $C62D: 86 6E
00C62F  1  86 5C            stx BaseMotionActive                     ; $C62F: 86 5C
00C631  1  86 7E            stx ActionSequenceCounter                     ; $C631: 86 7E
00C633  1  86 86            stx TrajectoryEvaluationEnabled                     ; $C633: 86 86
00C635  1  86 85            stx $85                     ; $C635: 86 85
00C637  1  86 83            stx ObjectApproachCount                     ; $C637: 86 83
00C639  1  86 6F            stx PendingEvent                     ; $C639: 86 6F
00C63B  1  86 A2            stx ObjectSequenceState                     ; $C63B: 86 A2
00C63D  1  86 BC            stx $BC                     ; $C63D: 86 BC
00C63F  1               
00C63F  1  8E 6E 05         stx $056E                   ; $C63F: 8E 6E 05
00C642  1               
00C642  1  86 9E            stx $9E                     ; $C642: 86 9E
00C644  1               
00C644  1  E8               inx                         ; $C644: E8
00C645  1                                               ; X = $01
00C645  1               
00C645  1  86 96            stx $96                     ; $C645: 86 96
00C647  1  86 97            stx $97                     ; $C647: 86 97
00C649  1  86 98            stx $98                     ; $C649: 86 98
00C64B  1               
00C64B  1               ; ----------------------------------------------------------------------------
00C64B  1               ; Reset coordinate-related structures.
00C64B  1               ; ----------------------------------------------------------------------------
00C64B  1               
00C64B  1  20 43 C9         jsr ClearBaseAccelerationFields            ; $C64B: 20 43 C9
00C64E  1  20 4F C9         jsr ClearBasePositionFields            ; $C64E: 20 4F C9
00C651  1               
00C651  1               ; ----------------------------------------------------------------------------
00C651  1               ; Run three inline-command handlers.
00C651  1               ; ----------------------------------------------------------------------------
00C651  1               
00C651  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $C651: 20 0A EB
00C654  1               
00C654  1  25 5A D8         .byte $25,$5A,$D8           ; $C654-$C656
00C657  1               
00C657  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $C657: 20 0A EB
00C65A  1               
00C65A  1  0E 66 D1         .byte $0E,$66,$D1           ; $C65A-$C65C
00C65D  1               
00C65D  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $C65D: 20 0A EB
00C660  1               
00C660  1  1F 76 CA         .byte $1F,$76,$CA           ; $C660-$C662
00C663  1               
00C663  1               ; ----------------------------------------------------------------------------
00C663  1               ; Process command $08.
00C663  1               ; ----------------------------------------------------------------------------
00C663  1               
00C663  1  A2 08            ldx #$08                    ; $C663: A2 08
00C665  1  20 4E EB         jsr UpdateObjectEventBank_Exchange                   ; $C665: 20 4E EB
00C668  1               
00C668  1               ; ----------------------------------------------------------------------------
00C668  1               ; Walk a 22-entry table in reverse.
00C668  1               ;
00C668  1               ; X begins at $15 and reaches $00. Each byte from $C6E1,X is passed in Y
00C668  1               ; to the routine at $EB66.
00C668  1               ; ----------------------------------------------------------------------------
00C668  1               
00C668  1  A2 15            ldx #$15                    ; $C668: A2 15
00C66A  1               
00C66A  1               ProcessRoundEventSlotTable:      ; $C66A
00C66A  1  BC E1 C6         ldy RoundEventSlotTable,x            ; $C66A: BC E1 C6
00C66D  1  20 66 EB         jsr DispatchNextQueuedEvent                   ; $C66D: 20 66 EB
00C670  1               
00C670  1  CA               dex                         ; $C670: CA
00C671  1  10 F7            bpl ProcessRoundEventSlotTable
00C673  1                                               ; $C671: 10 F7
00C673  1               
00C673  1               ; ----------------------------------------------------------------------------
00C673  1               ; Write one inline character at the selected PPU destination.
00C673  1               ; ----------------------------------------------------------------------------
00C673  1               
00C673  1  A9 3F            lda #$3F                    ; $C673: A9 3F
00C675  1  A2 07            ldx #$07                    ; $C675: A2 07
00C677  1  A0 01            ldy #$01                    ; $C677: A0 01
00C679  1               
00C679  1  20 17 EA         jsr CopyInlineDisplayRecord                   ; $C679: 20 17 EA
00C67C  1               
00C67C  1  01 28            .byte $01,$28               ; $C67C-$C67D
00C67E  1                                               ; One encoded character: $28.
00C67E  1               
00C67E  1               ; ----------------------------------------------------------------------------
00C67E  1               ; If $60 is zero and $65 is nonzero, run the helper at $CFA6 and clear $65.
00C67E  1               ; ----------------------------------------------------------------------------
00C67E  1               
00C67E  1               ApplyPendingScoreUpdate: ; $C67E
00C67E  1  A5 60            lda PendingStateTransition                     ; $C67E: A5 60
00C680  1  D0 0B            bne StartPostRoundDelay ; $C680: D0 0B
00C682  1               
00C682  1  A5 65            lda PendingScoreIncrement                     ; $C682: A5 65
00C684  1  F0 07            beq StartPostRoundDelay ; $C684: F0 07
00C686  1               
00C686  1  20 A6 CF         jsr UpdateCountersAndDisplay                   ; $C686: 20 A6 CF
00C689  1               
00C689  1  A9 00            lda #$00                    ; $C689: A9 00
00C68B  1  85 65            sta PendingScoreIncrement                     ; $C68B: 85 65
00C68D  1               
00C68D  1               ; ----------------------------------------------------------------------------
00C68D  1               ; Wait for $6F to become zero, then count down $48.
00C68D  1               ; ----------------------------------------------------------------------------
00C68D  1               
00C68D  1               StartPostRoundDelay:        ; $C68D
00C68D  1  A9 1E            lda #$1E                    ; $C68D: A9 1E
00C68F  1  85 48            sta $48                     ; $C68F: 85 48
00C691  1               
00C691  1               WaitPostRoundFrame:         ; $C691
00C691  1  20 48 EB         jsr SelectObjectEventBank1                   ; $C691: 20 48 EB
00C694  1               
00C694  1  A5 6F            lda PendingEvent                     ; $C694: A5 6F
00C696  1  D0 F5            bne StartPostRoundDelay ; $C696: D0 F5
00C698  1               
00C698  1  C6 48            dec $48                     ; $C698: C6 48
00C69A  1  D0 F5            bne WaitPostRoundFrame  ; $C69A: D0 F5
00C69C  1               
00C69C  1               ; ----------------------------------------------------------------------------
00C69C  1               ; If both $45 and $46 are zero, return to the initialization point at $C5BA.
00C69C  1               ; ----------------------------------------------------------------------------
00C69C  1               
00C69C  1  A5 45            lda MatchCompleteFlag                     ; $C69C: A5 45
00C69E  1  05 46            ora StateSequenceActive                     ; $C69E: 05 46
00C6A0  1  D0 03            bne ProcessPostRoundEvents
00C6A2  1                                               ; $C6A0: D0 03
00C6A2  1               
00C6A2  1  4C BA C5         jmp ResumeRoundSetupAtSelectionDisplay                   ; $C6A2: 4C BA C5
00C6A5  1               
00C6A5  1               ; ----------------------------------------------------------------------------
00C6A5  1               ; Process two indexed event slots and wait ten ticks.
00C6A5  1               ; ----------------------------------------------------------------------------
00C6A5  1               
00C6A5  1               ProcessPostRoundEvents:     ; $C6A5
00C6A5  1  A0 0D            ldy #$0D                    ; $C6A5: A0 0D
00C6A7  1  20 66 EB         jsr DispatchNextQueuedEvent                   ; $C6A7: 20 66 EB
00C6AA  1               
00C6AA  1  A0 0F            ldy #$0F                    ; $C6AA: A0 0F
00C6AC  1  20 66 EB         jsr DispatchNextQueuedEvent                   ; $C6AC: 20 66 EB
00C6AF  1               
00C6AF  1  A9 0A            lda #$0A                    ; $C6AF: A9 0A
00C6B1  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $C6B1: 20 41 EB
00C6B4  1               
00C6B4  1               ; ----------------------------------------------------------------------------
00C6B4  1               ; If $46 is active, decrement one of the two counters at $51/$52.
00C6B4  1               ; The selected counter depends on the low bit of $33.
00C6B4  1               ; ----------------------------------------------------------------------------
00C6B4  1               
00C6B4  1  A5 46            lda StateSequenceActive                     ; $C6B4: A5 46
00C6B6  1  F0 0D            beq CheckPostRoundContinuation ; $C6B6: F0 0D
00C6B8  1               
00C6B8  1  A5 33            lda RoundStateIndex                     ; $C6B8: A5 33
00C6BA  1  29 01            and #$01                    ; $C6BA: 29 01
00C6BC  1  AA               tax                         ; $C6BC: AA
00C6BD  1               
00C6BD  1  D6 51            dec Counter51,x                   ; $C6BD: D6 51
00C6BF  1  10 04            bpl CheckPostRoundContinuation ; $C6BF: 10 04
00C6C1  1               
00C6C1  1  A9 08            lda #$08                    ; $C6C1: A9 08
00C6C3  1  95 51            sta Counter51,x                   ; $C6C3: 95 51
00C6C5  1               
00C6C5  1               ; ----------------------------------------------------------------------------
00C6C5  1               ; If $45 is zero, return to the setup point at $C5A4.
00C6C5  1               ; Otherwise, update state and advance $33.
00C6C5  1               ; ----------------------------------------------------------------------------
00C6C5  1               
00C6C5  1               CheckPostRoundContinuation:        ; $C6C5
00C6C5  1  A5 45            lda MatchCompleteFlag                     ; $C6C5: A5 45
00C6C7  1  D0 03            bne AdvanceRoundNumber    ; $C6C7: D0 03
00C6C9  1               
00C6C9  1  4C A4 C5         jmp ResumeRoundSetupAtRandomDirection                   ; $C6C9: 4C A4 C5
00C6CC  1               
00C6CC  1               AdvanceRoundNumber:           ; $C6CC
00C6CC  1  20 A6 CF         jsr UpdateCountersAndDisplay                   ; $C6CC: 20 A6 CF
00C6CF  1               
00C6CF  1  E6 33            inc RoundStateIndex                     ; $C6CF: E6 33
00C6D1  1               
00C6D1  1  A5 33            lda RoundStateIndex                     ; $C6D1: A5 33
00C6D3  1  C9 12            cmp #$12                    ; $C6D3: C9 12
00C6D5  1  F0 31            beq InitializeResultsPosition                   ; $C6D5: F0 31
00C6D7  1               
00C6D7  1  20 48 EB         jsr SelectObjectEventBank1                   ; $C6D7: 20 48 EB
00C6DA  1               
00C6DA  1  A5 EF            lda GameplaySuspended                     ; $C6DA: A5 EF
00C6DC  1  D0 6C            bne InitializeTitleScreen                   ; $C6DC: D0 6C
00C6DE  1               
00C6DE  1  4C 66 C5         jmp SelectRoundMusicCue                   ; $C6DE: 4C 66 C5
00C6E1  1               
00C6E1  1               ; ============================================================================
00C6E1  1               ; Table referenced by the loop at $C66A.
00C6E1  1               ;
00C6E1  1               ; The table begins at CPU $C6E1 and remains in the untouched ROM for the next
00C6E1  1               ; pass. Its first bytes are:
00C6E1  1               ;
00C6E1  1               ;   $04,$06,$08,$0A,$0C,$0E,$10,$12 ...
00C6E1  1               ; ============================================================================
00C6E1  1               
00C6E1  1               ; ============================================================================
00C6E1  1               ; $C6E1-$C6F6
00C6E1  1               ; Event-slot/index lookup table
00C6E1  1               ; ============================================================================
00C6E1  1               
00C6E1  1               RoundEventSlotTable:                     ; $C6E1
00C6E1  1  04 06 08 0A      .byte $04,$06,$08,$0A
00C6E5  1  0C 0E 10 12      .byte $0C,$0E,$10,$12
00C6E9  1  14 16 1E 20      .byte $14,$16,$1E,$20
00C6ED  1  22 24 26 11      .byte $22,$24,$26,$11
00C6F1  1  15 17 19 1D      .byte $15,$17,$19,$1D
00C6F5  1  1F 29            .byte $1F,$29
00C6F7  1               
00C6F7  1               ; ============================================================================
00C6F7  1               ; $C6F7-$C7B0
00C6F7  1               ; State completion, message display, PPU setup, and return to the main loop
00C6F7  1               ; ============================================================================
00C6F7  1               
00C6F7  1               CompleteMatchState:                   ; $C6F7
00C6F7  1  E6 33            inc RoundStateIndex                     ; $C6F7: E6 33
00C6F9  1               
00C6F9  1  A5 66            lda InningOrSharedScore                     ; $C6F9: A5 66
00C6FB  1  D0 0B            bne InitializeResultsPosition
00C6FD  1                                               ; $C6FB: D0 0B
00C6FD  1               
00C6FD  1               ; ----------------------------------------------------------------------------
00C6FD  1               ; Draw one encoded character.
00C6FD  1               ; ----------------------------------------------------------------------------
00C6FD  1               
00C6FD  1  A9 20            lda #$20                    ; $C6FD: A9 20
00C6FF  1  A2 B3            ldx #$B3                    ; $C6FF: A2 B3
00C701  1  A0 01            ldy #$01                    ; $C701: A0 01
00C703  1               
00C703  1  20 17 EA         jsr CopyInlineDisplayRecord                   ; $C703: 20 17 EA
00C706  1               
00C706  1  01 32            .byte $01,$32               ; $C706-$C707
00C708  1               
00C708  1               ; ----------------------------------------------------------------------------
00C708  1               ; Initialize signed position/state values.
00C708  1               ; ----------------------------------------------------------------------------
00C708  1               
00C708  1               InitializeResultsPosition: ; $C708
00C708  1  A9 80            lda #$80                    ; $C708: A9 80
00C70A  1  8D 3B 05         sta $053B                   ; $C70A: 8D 3B 05
00C70D  1  85 B7            sta PositionSignState                     ; $C70D: 85 B7
00C70F  1               
00C70F  1               ; ----------------------------------------------------------------------------
00C70F  1               ; Draw a ten-character encoded message.
00C70F  1               ; ----------------------------------------------------------------------------
00C70F  1               
00C70F  1  A9 20            lda #$20                    ; $C70F: A9 20
00C711  1  A2 EB            ldx #$EB                    ; $C711: A2 EB
00C713  1  A0 0A            ldy #$0A                    ; $C713: A0 0A
00C715  1  18               clc                         ; $C715: 18
00C716  1               
00C716  1  20 17 EA         jsr CopyInlineDisplayRecord                   ; $C716: 20 17 EA
00C719  1               
00C719  1  0A               .byte $0A                   ; $C719
00C71A  1  25 10 0A 16      .byte $25,$10,$0A,$16,$0E   ; $C71A-$C71E
00C71E  1  0E           
00C71F  1  25 1C 0E 1D      .byte $25,$1C,$0E,$1D,$25   ; $C71F-$C723
00C723  1  25           
00C724  1               
00C724  1               ; ----------------------------------------------------------------------------
00C724  1               ; Set timing, process event slot two, and invoke an inline command.
00C724  1               ; ----------------------------------------------------------------------------
00C724  1               
00C724  1  A9 04            lda #$04                    ; $C724: A9 04
00C726  1  85 FD            sta $FD                     ; $C726: 85 FD
00C728  1               
00C728  1  A0 02            ldy #$02                    ; $C728: A0 02
00C72A  1  20 66 EB         jsr DispatchNextQueuedEvent                   ; $C72A: 20 66 EB
00C72D  1               
00C72D  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $C72D: 20 0A EB
00C730  1               
00C730  1  02 88 C4         .byte $02,$88,$C4           ; $C730-$C732
00C733  1               
00C733  1               ; ----------------------------------------------------------------------------
00C733  1               ; Wait for ten iterations of a $3C-tick delay.
00C733  1               ; ----------------------------------------------------------------------------
00C733  1               
00C733  1  A9 0A            lda #$0A                    ; $C733: A9 0A
00C735  1  85 49            sta $49                     ; $C735: 85 49
00C737  1               
00C737  1               ResultsDelayLoop:         ; $C737
00C737  1  A9 3C            lda #$3C                    ; $C737: A9 3C
00C739  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $C739: 20 41 EB
00C73C  1               
00C73C  1  C6 49            dec $49                     ; $C73C: C6 49
00C73E  1  D0 F7            bne ResultsDelayLoop  ; $C73E: D0 F7
00C740  1               
00C740  1               ; ----------------------------------------------------------------------------
00C740  1               ; Disable APU channels and clear state.
00C740  1               ; ----------------------------------------------------------------------------
00C740  1               
00C740  1  A9 00            lda #$00                    ; $C740: A9 00
00C742  1  8D 00 01         sta $0100                   ; $C742: 8D 00 01
00C745  1  8D 15 40         sta APUSTATUS               ; $C745: 8D 15 40
00C748  1  85 1E            sta SessionActive                     ; $C748: 85 1E
00C74A  1               
00C74A  1               ; ----------------------------------------------------------------------------
00C74A  1               ; Shared entry point used by RESET and other transition paths.
00C74A  1               ; ----------------------------------------------------------------------------
00C74A  1               
00C74A  1               InitializeTitleScreen:                   ; $C74A
00C74A  1  20 9D EB         jsr InitializeQueuedEventSystem                   ; $C74A: 20 9D EB
00C74D  1               
00C74D  1  A9 00            lda #$00                    ; $C74D: A9 00
00C74F  1  85 EF            sta GameplaySuspended                     ; $C74F: 85 EF
00C751  1               
00C751  1  E6 1D            inc TransitionActive                     ; $C751: E6 1D
00C753  1               
00C753  1               ; ----------------------------------------------------------------------------
00C753  1               ; Configure PPU shadow state.
00C753  1               ; ----------------------------------------------------------------------------
00C753  1               
00C753  1  A9 80            lda #$80                    ; $C753: A9 80
00C755  1  85 DD            sta PpuCtrlShadow                     ; $C755: 85 DD
00C757  1               
00C757  1  20 6C E9         jsr DisablePpuRendering     ; $C757: 20 6C E9
00C75A  1               
00C75A  1  A9 25            lda #$25                    ; $C75A: A9 25
00C75C  1  20 85 E9         jsr FillPpuMemoryAfterValueSaved                   ; $C75C: 20 85 E9
00C75F  1               
00C75F  1               ; ----------------------------------------------------------------------------
00C75F  1               ; $EA63 consumes the two bytes immediately following each JSR.
00C75F  1               ; ----------------------------------------------------------------------------
00C75F  1               
00C75F  1  20 63 EA         jsr ProcessInlinePpuStream                   ; $C75F: 20 63 EA
00C762  1               
00C762  1  8D F8            .byte $8D,$F8               ; $C762-$C763
00C764  1               
00C764  1  20 63 EA         jsr ProcessInlinePpuStream                   ; $C764: 20 63 EA
00C767  1               
00C767  1  00 C0            .byte $00,$C0               ; $C767-$C768
00C769  1               
00C769  1  20 78 E9         jsr EnableNmiAndWaitForFrame                   ; $C769: 20 78 E9
00C76C  1               
00C76C  1               ; ----------------------------------------------------------------------------
00C76C  1               ; Enable the standard APU channels and initialize timing.
00C76C  1               ; ----------------------------------------------------------------------------
00C76C  1               
00C76C  1  A9 0F            lda #$0F                    ; $C76C: A9 0F
00C76E  1  8D 00 01         sta $0100                   ; $C76E: 8D 00 01
00C771  1  8D 15 40         sta APUSTATUS               ; $C771: 8D 15 40
00C774  1               
00C774  1  A9 08            lda #$08                    ; $C774: A9 08
00C776  1  85 FD            sta $FD                     ; $C776: 85 FD
00C778  1               
00C778  1               ; ----------------------------------------------------------------------------
00C778  1               ; Refresh state and wait through three input-release cycles.
00C778  1               ;
00C778  1               ; The branch at $C78A targets $C77A, not $C783.
00C778  1               ; ----------------------------------------------------------------------------
00C778  1               
00C778  1  C6 40            dec ModeFlags                     ; $C778: C6 40
00C77A  1               
00C77A  1               RefreshTitleScreen:           ; $C77A
00C77A  1  E6 40            inc ModeFlags                     ; $C77A: E6 40
00C77C  1               
00C77C  1  20 CF E5         jsr QueueModeIndicatorTiles                   ; $C77C: 20 CF E5
00C77F  1               
00C77F  1  A9 03            lda #$03                    ; $C77F: A9 03
00C781  1  85 1B            sta $1B                     ; $C781: 85 1B
00C783  1               
00C783  1               WaitForTitleInputRelease:         ; $C783
00C783  1  20 48 EB         jsr SelectObjectEventBank1                   ; $C783: 20 48 EB
00C786  1               
00C786  1  A5 15            lda ControllerPressed1                     ; $C786: A5 15
00C788  1  29 20            and #$20                    ; $C788: 29 20
00C78A  1  D0 EE            bne RefreshTitleScreen    ; $C78A: D0 EE
00C78C  1               
00C78C  1  A5 E3            lda FrameCounter                     ; $C78C: A5 E3
00C78E  1  D0 F3            bne WaitForTitleInputRelease  ; $C78E: D0 F3
00C790  1               
00C790  1  C6 1B            dec $1B                     ; $C790: C6 1B
00C792  1  D0 EF            bne WaitForTitleInputRelease  ; $C792: D0 EF
00C794  1               
00C794  1               ; ----------------------------------------------------------------------------
00C794  1               ; Restore transition state and return to the initialization loop.
00C794  1               ;
00C794  1               ; A is zero when execution reaches STA $1D because the successful DEC $1B
00C794  1               ; produced zero.
00C794  1               ; ----------------------------------------------------------------------------
00C794  1               
00C794  1  85 1D            sta TransitionActive                     ; $C794: 85 1D
00C796  1               
00C796  1  A9 01            lda #$01                    ; $C796: A9 01
00C798  1  85 EF            sta GameplaySuspended                     ; $C798: 85 EF
00C79A  1               
00C79A  1  A9 00            lda #$00                    ; $C79A: A9 00
00C79C  1  8D 96 05         sta $0596                   ; $C79C: 8D 96 05
00C79F  1  8D 00 01         sta $0100                   ; $C79F: 8D 00 01
00C7A2  1  8D 15 40         sta APUSTATUS               ; $C7A2: 8D 15 40
00C7A5  1               
00C7A5  1  20 9D EB         jsr InitializeQueuedEventSystem                   ; $C7A5: 20 9D EB
00C7A8  1               
00C7A8  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $C7A8: 20 0A EB
00C7AB  1               
00C7AB  1  03 88 C4         .byte $03,$88,$C4           ; $C7AB-$C7AD
00C7AE  1               
00C7AE  1  4C AA C4         jmp InitializeSessionDisplay            ; $C7AE: 4C AA C4
00C7B1  1               
00C7B1  1               ; ============================================================================
00C7B1  1               ; $C7B1-$C7C8
00C7B1  1               ; Initialize object sorting/index tables.
00C7B1  1               ;
00C7B1  1               ; Called by RESET at $C422.
00C7B1  1               ; ============================================================================
00C7B1  1               
00C7B1  1               ; ----------------------------------------------------------------------------
00C7B1  1               ; Contract:
00C7B1  1               ;   Description: Initializes Sprite Sort Tables.
00C7B1  1               ;   Entry: Registers: A, X
00C7B1  1               ;   Returns/products: Registers/clobbers: A, X
00C7B1  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00C7B1  1               ;   Memory effects: $0377, $038c, $0399
00C7B1  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00C7B1  1               ;          comparison, load, or store path and are not a stable API product.
00C7B1  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00C7B1  1               ; ----------------------------------------------------------------------------
00C7B1  1               InitializeSpriteSortTables:                   ; $C7B1
00C7B1  1  A2 14            ldx #$14                    ; $C7B1: A2 14
00C7B3  1               
00C7B3  1               InitializeSpriteSortIndexLoop: ; $C7B3
00C7B3  1  8A               txa                         ; $C7B3: 8A
00C7B4  1  0A               asl                         ; $C7B4: 0A
00C7B5  1                                               ; A = X * 2
00C7B5  1               
00C7B5  1  9D 77 03         sta $0377,x                 ; $C7B5: 9D 77 03
00C7B8  1               
00C7B8  1  E0 0D            cpx #$0D                    ; $C7B8: E0 0D
00C7BA  1  B0 03            bcs InitializeNextSpriteSortIndex  ; $C7BA: B0 03
00C7BC  1               
00C7BC  1  9D 8C 03         sta $038C,x                 ; $C7BC: 9D 8C 03
00C7BF  1               
00C7BF  1               InitializeNextSpriteSortIndex:         ; $C7BF
00C7BF  1  CA               dex                         ; $C7BF: CA
00C7C0  1  D0 F1            bne InitializeSpriteSortIndexLoop
00C7C2  1                                               ; $C7C0: D0 F1
00C7C2  1               
00C7C2  1               ; ----------------------------------------------------------------------------
00C7C2  1               ; X is zero when the loop terminates.
00C7C2  1               ; Clear two additional entries.
00C7C2  1               ; ----------------------------------------------------------------------------
00C7C2  1               
00C7C2  1  8E 8C 03         stx $038C                   ; $C7C2: 8E 8C 03
00C7C5  1  8E 99 03         stx $0399                   ; $C7C5: 8E 99 03
00C7C8  1               
00C7C8  1  60               rts                         ; $C7C8: 60
00C7C9  1               
00C7C9  1               ; ============================================================================
00C7C9  1               ; $C7C9-$C7DC
00C7C9  1               ; Draw eight blank encoded characters.
00C7C9  1               ;
00C7C9  1               ; Called earlier from the state-initialization sequence at $C5BA.
00C7C9  1               ; ============================================================================
00C7C9  1               
00C7C9  1               ; ----------------------------------------------------------------------------
00C7C9  1               ; Contract:
00C7C9  1               ;   Description: Clears or resets Eight Character Field.
00C7C9  1               ;   Entry: No register input inferred
00C7C9  1               ;   Returns/products: Registers/clobbers: A, X, Y; Flags: condition flags may carry result state
00C7C9  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00C7C9  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00C7C9  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00C7C9  1               ;          comparison, load, or store path and are not a stable API product.
00C7C9  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00C7C9  1               ; ----------------------------------------------------------------------------
00C7C9  1               ClearEightCharacterField:                   ; $C7C9
00C7C9  1  18               clc                         ; $C7C9: 18
00C7CA  1               
00C7CA  1  A9 20            lda #$20                    ; $C7CA: A9 20
00C7CC  1  A2 EC            ldx #$EC                    ; $C7CC: A2 EC
00C7CE  1  A0 08            ldy #$08                    ; $C7CE: A0 08
00C7D0  1               
00C7D0  1  20 17 EA         jsr CopyInlineDisplayRecord                   ; $C7D0: 20 17 EA
00C7D3  1               
00C7D3  1                   ; Inline text consumed by $EA17:
00C7D3  1                   ; count $08 followed by eight blank characters ($25).
00C7D3  1  08               .byte $08                   ; $C7D3
00C7D4  1  25 25 25 25      .byte $25,$25,$25,$25       ; $C7D4-$C7D7
00C7D8  1  25 25 25 25      .byte $25,$25,$25,$25       ; $C7D8-$C7DB
00C7DC  1               
00C7DC  1  60               rts                         ; $C7DC: 60
00C7DD  1               
00C7DD  1               ; ============================================================================
00C7DD  1               ; $C7DD-$C819
00C7DD  1               ; Write a seven-byte PPU data sequence and update two OAM entries.
00C7DD  1               ; ============================================================================
00C7DD  1               
00C7DD  1               ; ----------------------------------------------------------------------------
00C7DD  1               ; Contract:
00C7DD  1               ;   Description: Queues Player Selection Display.
00C7DD  1               ;   Entry: Registers: A, X, Y; Memory: $33, $34, $3e, $c02a, $c030, $e1, $13, $4b
00C7DD  1               ;   Returns/products: Registers/clobbers: A, X, Y
00C7DD  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00C7DD  1               ;   Memory effects: $02fd, $02ff, $32
00C7DD  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00C7DD  1               ;          comparison, load, or store path and are not a stable API product.
00C7DD  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 2.
00C7DD  1               ; ----------------------------------------------------------------------------
00C7DD  1               QueuePlayerSelectionDisplay:                   ; $C7DD
00C7DD  1  18               clc                         ; $C7DD: 18
00C7DE  1               
00C7DE  1  A9 3F            lda #$3F                    ; $C7DE: A9 3F
00C7E0  1  A2 11            ldx #$11                    ; $C7E0: A2 11
00C7E2  1  A0 07            ldy #$07                    ; $C7E2: A0 07
00C7E4  1               
00C7E4  1  20 17 EA         jsr CopyInlineDisplayRecord                   ; $C7E4: 20 17 EA
00C7E7  1               
00C7E7  1               ; ----------------------------------------------------------------------------
00C7E7  1               ; Inline data consumed by $EA17.
00C7E7  1               ;
00C7E7  1               ; The first byte is the length, followed by seven data bytes.
00C7E7  1               ; ----------------------------------------------------------------------------
00C7E7  1               
00C7E7  1  07               .byte $07                   ; $C7E7: length
00C7E8  1  00 27 00 30      .byte $00,$27,$00,$30       ; $C7E8-$C7EB
00C7EC  1  00 27 00         .byte $00,$27,$00           ; $C7EC-$C7EE
00C7EF  1               
00C7EF  1               ; ----------------------------------------------------------------------------
00C7EF  1               ; Select one of the values at $34/$35 based on the low bit of $33.
00C7EF  1               ; Use that value as an index into the tables at $C02A and $C030.
00C7EF  1               ;
00C7EF  1               ; The resulting values are written into one pair of OAM entries.
00C7EF  1               ; ----------------------------------------------------------------------------
00C7EF  1               
00C7EF  1  A5 33            lda RoundStateIndex                     ; $C7EF: A5 33
00C7F1  1  29 01            and #$01                    ; $C7F1: 29 01
00C7F3  1               
00C7F3  1  48               pha                         ; $C7F3: 48
00C7F4  1                                               ; Save the selected side.
00C7F4  1               
00C7F4  1  AA               tax                         ; $C7F4: AA
00C7F5  1  B4 34            ldy PlayerOneSelection,x                   ; $C7F5: B4 34
00C7F7  1               
00C7F7  1  A6 3E            ldx PpuQueueOffset                     ; $C7F7: A6 3E
00C7F9  1               
00C7F9  1  B9 2A C0         lda $C02A,y                 ; $C7F9: B9 2A C0
00C7FC  1  9D FD 02         sta $02FD,x                 ; $C7FC: 9D FD 02
00C7FF  1               
00C7FF  1  B9 30 C0         lda $C030,y                 ; $C7FF: B9 30 C0
00C802  1  9D FF 02         sta $02FF,x                 ; $C802: 9D FF 02
00C805  1               
00C805  1               ; ----------------------------------------------------------------------------
00C805  1               ; Select the opposite $34/$35 entry and write the corresponding table values
00C805  1               ; into the other OAM pair.
00C805  1               ; ----------------------------------------------------------------------------
00C805  1               
00C805  1  68               pla
00C806  1  49 01            eor #$01
00C808  1  AA               tax
00C809  1               
00C809  1  B4 34            ldy $34,x
00C80B  1  A6 3E            ldx $3E
00C80D  1               
00C80D  1  B9 2A C0         lda $C02A,y
00C810  1  9D F9 02         sta $02F9,x
00C813  1               
00C813  1  B9 30 C0         lda $C030,y
00C816  1  9D FB 02         sta $02FB,x
00C819  1               
00C819  1  60               rts
00C81A  1               
00C81A  1               ; ============================================================================
00C81A  1               ; $C81A-$C84F
00C81A  1               ; Update paired selection indices from controller/state input.
00C81A  1               ;
00C81A  1               ; The routine works with two entries in the table at $32/$33. It selects an
00C81A  1               ; entry using $E1, modifies the selected value according to bits shifted from
00C81A  1               ; A, then verifies that the two entries are not equal.
00C81A  1               ; ============================================================================
00C81A  1               
00C81A  1               UpdatePlayerSelections:                   ; $C81A
00C81A  1  20 48 EB         jsr SelectObjectEventBank1                   ; $C81A: 20 48 EB
00C81D  1               
00C81D  1               SelectPlayerSelectionEntry:       ; $C81D
00C81D  1  A5 E1            lda CurrentObjectIndex                     ; $C81D: A5 E1
00C81F  1  AA               tax                         ; $C81F: AA
00C820  1               
00C820  1  B4 13            ldy InputState1,x                   ; $C820: B4 13
00C822  1               
00C822  1  45 4B            eor ActivePlayerSide                     ; $C822: 45 4B
00C824  1  AA               tax                         ; $C824: AA
00C825  1               
00C825  1  98               tya                         ; $C825: 98
00C826  1  B4 32            ldy SelectionValue0,x                   ; $C826: B4 32
00C828  1               
00C828  1               ; ----------------------------------------------------------------------------
00C828  1               ; Bit 0 selects whether to increment the current value.
00C828  1               ;
00C828  1               ; The value wraps from six back to zero.
00C828  1               ; ----------------------------------------------------------------------------
00C828  1               
00C828  1  4A               lsr                         ; $C828: 4A
00C829  1  90 07            bcc ApplySelectionDecrement
00C82B  1                                               ; $C829: 90 07
00C82B  1               
00C82B  1  C8               iny                         ; $C82B: C8
00C82C  1               
00C82C  1  C0 06            cpy #$06                    ; $C82C: C0 06
00C82E  1  90 02            bcc ApplySelectionDecrement
00C830  1                                               ; $C82E: 90 02
00C830  1               
00C830  1  A0 00            ldy #$00                    ; $C830: A0 00
00C832  1               
00C832  1               ; ----------------------------------------------------------------------------
00C832  1               ; Bit 1 selects whether to decrement the current value.
00C832  1               ;
00C832  1               ; The value wraps from zero to five.
00C832  1               ; ----------------------------------------------------------------------------
00C832  1               
00C832  1               ApplySelectionDecrement:    ; $C832
00C832  1  4A               lsr                         ; $C832: 4A
00C833  1  90 05            bcc SavePlayerSelection  ; $C833: 90 05
00C835  1               
00C835  1  88               dey                         ; $C835: 88
00C836  1  10 02            bpl SavePlayerSelection  ; $C836: 10 02
00C838  1               
00C838  1  A0 05            ldy #$05                    ; $C838: A0 05
00C83A  1               
00C83A  1               SavePlayerSelection:         ; $C83A
00C83A  1  94 32            sty SelectionValue0,x                   ; $C83A: 94 32
00C83C  1               
00C83C  1               ; ----------------------------------------------------------------------------
00C83C  1               ; Select the opposite table entry and ensure both selections differ.
00C83C  1               ; If they are equal, wait for another update and retry.
00C83C  1               ; ----------------------------------------------------------------------------
00C83C  1               
00C83C  1  8A               txa                         ; $C83C: 8A
00C83D  1  49 01            eor #$01                    ; $C83D: 49 01
00C83F  1  AA               tax                         ; $C83F: AA
00C840  1               
00C840  1  98               tya                         ; $C840: 98
00C841  1  D5 32            cmp SelectionValue0,x                   ; $C841: D5 32
00C843  1  F0 D8            beq SelectPlayerSelectionEntry
00C845  1                                               ; $C843: F0 D8
00C845  1               
00C845  1               ; ----------------------------------------------------------------------------
00C845  1               ; Continue waiting while the selected input/state value is nonnegative.
00C845  1               ; Otherwise, decrement $43 and leave through the common engine exit.
00C845  1               ; ----------------------------------------------------------------------------
00C845  1               
00C845  1  A6 E1            ldx CurrentObjectIndex                     ; $C845: A6 E1
00C847  1               
00C847  1  B5 13            lda InputState1,x                   ; $C847: B5 13
00C849  1  10 CF            bpl UpdatePlayerSelections            ; $C849: 10 CF
00C84B  1               
00C84B  1  C6 43            dec $43                     ; $C84B: C6 43
00C84D  1               
00C84D  1  4C 6A EB         jmp CommonEngineExit                   ; $C84D: 4C 6A EB
00C850  1               
00C850  1               ; ============================================================================
00C850  1               ; $C850-$C859
00C850  1               ; Generate a random value in the range $00-$05.
00C850  1               ; ============================================================================
00C850  1               
00C850  1               ; ----------------------------------------------------------------------------
00C850  1               ; Contract:
00C850  1               ;   Description: Implements Random 0 To 5.
00C850  1               ;   Entry: Registers: A
00C850  1               ;   Returns/products: Registers/clobbers: A; Flags: condition flags may carry result state
00C850  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00C850  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00C850  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00C850  1               ;          comparison, load, or store path and are not a stable API product.
00C850  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 2.
00C850  1               ; ----------------------------------------------------------------------------
00C850  1               Random0To5:        ; $C850
00C850  1  20 F5 E5         jsr AdvanceRandomState                   ; $C850: 20 F5 E5
00C853  1  29 07            and #$07                    ; $C853: 29 07
00C855  1  C9 06            cmp #$06                    ; $C855: C9 06
00C857  1  B0 F7            bcs Random0To5 ; $C857: B0 F7
00C859  1               
00C859  1  60               rts                         ; $C859: 60
00C85A  1               
00C85A  1               ; ============================================================================
00C85A  1               ; $C85A-$C87D
00C85A  1               ; Build four 16-byte PPU command/data blocks in the queue at $0300.
00C85A  1               ;
00C85A  1               ; The destination high byte begins at $21. Four blocks are generated for:
00C85A  1               ;
00C85A  1               ;   $21xx
00C85A  1               ;   $22xx
00C85A  1               ;   $23xx
00C85A  1               ;   $24xx
00C85A  1               ;
00C85A  1               ; Each block is filled with sixteen $26 bytes.
00C85A  1               ; ============================================================================
00C85A  1               
00C85A  1               ; ----------------------------------------------------------------------------
00C85A  1               ; Contract:
00C85A  1               ;   Description: Implements Fill Selection Background Blocks.
00C85A  1               ;   Entry: Registers: A, X, Y; Memory: $4a
00C85A  1               ;   Returns/products: Registers/clobbers: A, X, Y
00C85A  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00C85A  1               ;   Memory effects: $44, $4a, $0300
00C85A  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00C85A  1               ;          comparison, load, or store path and are not a stable API product.
00C85A  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00C85A  1               ; ----------------------------------------------------------------------------
00C85A  1               FillSelectionBackgroundBlocks:                   ; $C85A
00C85A  1  A9 00            lda #$00                    ; $C85A: A9 00
00C85C  1  85 44            sta PlayerSelectionActive                     ; $C85C: 85 44
00C85E  1               
00C85E  1  A9 88            lda #$88                    ; $C85E: A9 88
00C860  1               
00C860  1               FillNextBackgroundBlock:         ; $C860
00C860  1  85 4A            sta $4A                     ; $C860: 85 4A
00C862  1  AA               tax                         ; $C862: AA
00C863  1               
00C863  1  18               clc                         ; $C863: 18
00C864  1               
00C864  1  A9 21            lda #$21                    ; $C864: A9 21
00C866  1  A0 10            ldy #$10                    ; $C866: A0 10
00C868  1  20 3E EA         jsr AllocateDisplayBufferRecord                   ; $C868: 20 3E EA
00C86B  1               
00C86B  1               ; ----------------------------------------------------------------------------
00C86B  1               ; Fill sixteen queue bytes with $26.
00C86B  1               ;
00C86B  1               ; X is expected to point into the PPU command queue after the setup call above.
00C86B  1               ; ----------------------------------------------------------------------------
00C86B  1               
00C86B  1  A0 10            ldy #$10                    ; $C86B: A0 10
00C86D  1  A9 26            lda #$26                    ; $C86D: A9 26
00C86F  1               
00C86F  1               FillBackgroundBlock:         ; $C86F
00C86F  1  9D 00 03         sta $0300,x                 ; $C86F: 9D 00 03
00C872  1               
00C872  1  E8               inx                         ; $C872: E8
00C873  1  88               dey                         ; $C873: 88
00C874  1  D0 F9            bne FillBackgroundBlock  ; $C874: D0 F9
00C876  1               
00C876  1               ; ----------------------------------------------------------------------------
00C876  1               ; Advance the saved queue/destination value by $20.
00C876  1               ; Continue until the addition carries.
00C876  1               ; ----------------------------------------------------------------------------
00C876  1               
00C876  1  A5 4A            lda $4A                     ; $C876: A5 4A
00C878  1  18               clc                         ; $C878: 18
00C879  1  69 20            adc #$20                    ; $C879: 69 20
00C87B  1  90 E3            bcc FillNextBackgroundBlock  ; $C87B: 90 E3
00C87D  1               
00C87D  1  60               rts                         ; $C87D: 60
00C87E  1               
00C87E  1               ; ============================================================================
00C87E  1               ; $C87E-$C8A1
00C87E  1               ; Derive paired state values in $0F and $10.
00C87E  1               ;
00C87E  1               ; Both outputs are cleared when $EF is nonzero. Otherwise, the routine combines
00C87E  1               ; bits from $40, $4B, and $33, then stores complementary values in $0F/$10.
00C87E  1               ; Carry from LSR $40 is used to conditionally increment each result.
00C87E  1               ; ============================================================================
00C87E  1               
00C87E  1               ; ----------------------------------------------------------------------------
00C87E  1               ; Contract:
00C87E  1               ;   Description: Calculates Controller Assignments.
00C87E  1               ;   Entry: Registers: A; Memory: $ef, $40, $4b, $33
00C87E  1               ;   Returns/products: Registers/clobbers: A
00C87E  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00C87E  1               ;   Memory effects: $0f, $10
00C87E  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00C87E  1               ;          comparison, load, or store path and are not a stable API product.
00C87E  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00C87E  1               ; ----------------------------------------------------------------------------
00C87E  1               CalculateControllerAssignments:                   ; $C87E
00C87E  1  A9 00            lda #$00                    ; $C87E: A9 00
00C880  1  85 0F            sta DerivedControl0                     ; $C880: 85 0F
00C882  1  85 10            sta $10                     ; $C882: 85 10
00C884  1               
00C884  1  A5 EF            lda GameplaySuspended                     ; $C884: A5 EF
00C886  1  D0 19            bne ControllerAssignmentReturn     ; $C886: D0 19
00C888  1               
00C888  1  A5 40            lda ModeFlags                     ; $C888: A5 40
00C88A  1  4A               lsr                         ; $C88A: 4A
00C88B  1                                               ; Carry receives bit 0 of $40.
00C88B  1               
00C88B  1  A5 40            lda ModeFlags                     ; $C88B: A5 40
00C88D  1  45 4B            eor ActivePlayerSide                     ; $C88D: 45 4B
00C88F  1  45 33            eor RoundStateIndex                     ; $C88F: 45 33
00C891  1  29 01            and #$01                    ; $C891: 29 01
00C893  1  85 10            sta $10                     ; $C893: 85 10
00C895  1               
00C895  1  90 02            bcc CalculateOppositeControllerAssignment ; $C895: 90 02
00C897  1               
00C897  1  E6 10            inc $10                     ; $C897: E6 10
00C899  1               
00C899  1               CalculateOppositeControllerAssignment:        ; $C899
00C899  1  49 01            eor #$01                    ; $C899: 49 01
00C89B  1  85 0F            sta DerivedControl0                     ; $C89B: 85 0F
00C89D  1               
00C89D  1  90 02            bcc ControllerAssignmentReturn     ; $C89D: 90 02
00C89F  1               
00C89F  1  E6 0F            inc DerivedControl0                     ; $C89F: E6 0F
00C8A1  1               
00C8A1  1               ControllerAssignmentReturn:            ; $C8A1
00C8A1  1  60               rts                         ; $C8A1: 60
00C8A2  1               
00C8A2  1               ; ============================================================================
00C8A2  1               ; $C8A2-$C8BA
00C8A2  1               ; Initialize the four-byte table at $0598-$059B.
00C8A2  1               ;
00C8A2  1               ; For each Y value from 3 down to 1:
00C8A2  1               ;   1. Compute A = Y * 2.
00C8A2  1               ;   2. Search $9F-$A1 for a matching value.
00C8A2  1               ;   3. Store the matching X index into $0598,Y.
00C8A2  1               ;   4. Store $FF when no match is found.
00C8A2  1               ;
00C8A2  1               ; Finally, clear $0598 because Y is zero when the loop terminates.
00C8A2  1               ; ============================================================================
00C8A2  1               
00C8A2  1               ; ----------------------------------------------------------------------------
00C8A2  1               ; Contract:
00C8A2  1               ;   Description: Initializes Object State Lookup.
00C8A2  1               ;   Entry: Registers: A, X, Y; Memory: $9f
00C8A2  1               ;   Returns/products: Registers/clobbers: A, X, Y
00C8A2  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00C8A2  1               ;   Memory effects: $0598
00C8A2  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00C8A2  1               ;          comparison, load, or store path and are not a stable API product.
00C8A2  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00C8A2  1               ; ----------------------------------------------------------------------------
00C8A2  1               InitializeObjectStateLookup:                   ; $C8A2
00C8A2  1  A0 03            ldy #$03                    ; $C8A2: A0 03
00C8A4  1               
00C8A4  1               Routine_C8A4_NextEntry:         ; $C8A4
00C8A4  1  98               tya                         ; $C8A4: 98
00C8A5  1  0A               asl                         ; $C8A5: 0A
00C8A6  1                                               ; A = Y * 2
00C8A6  1               
00C8A6  1  A2 02            ldx #$02                    ; $C8A6: A2 02
00C8A8  1               
00C8A8  1               Routine_C8A8_SearchValues:      ; $C8A8
00C8A8  1  D5 9F            cmp SecondaryActorState0,x                   ; $C8A8: D5 9F
00C8AA  1  F0 05            beq Routine_C8B1_SaveResult ; $C8AA: F0 05
00C8AC  1               
00C8AC  1  CA               dex                         ; $C8AC: CA
00C8AD  1  10 F9            bpl Routine_C8A8_SearchValues
00C8AF  1                                               ; $C8AD: 10 F9
00C8AF  1               
00C8AF  1  A9 FF            lda #$FF                    ; $C8AF: A9 FF
00C8B1  1                                               ; No matching entry was found.
00C8B1  1               
00C8B1  1               Routine_C8B1_SaveResult:        ; $C8B1
00C8B1  1  99 98 05         sta $0598,y                 ; $C8B1: 99 98 05
00C8B4  1               
00C8B4  1  88               dey                         ; $C8B4: 88
00C8B5  1  D0 ED            bne Routine_C8A4_NextEntry  ; $C8B5: D0 ED
00C8B7  1               
00C8B7  1               ; ----------------------------------------------------------------------------
00C8B7  1               ; Y is zero when the loop exits.
00C8B7  1               ; Clear the first table entry at $0598.
00C8B7  1               ; ----------------------------------------------------------------------------
00C8B7  1               
00C8B7  1  8C 98 05         sty $0598                   ; $C8B7: 8C 98 05
00C8BA  1               
00C8BA  1  60               rts                         ; $C8BA: 60
00C8BB  1               
00C8BB  1               ; ============================================================================
00C8BB  1               ; $C8BB-$C8E7
00C8BB  1               ; Expand a linked or variable-length record list into the buffer at $0400,X.
00C8BB  1               ;
00C8BB  1               ; Entry:
00C8BB  1               ;   X appears to be the destination offset into $0400.
00C8BB  1               ;   $00/$01 points to an inline or external pointer record.
00C8BB  1               ;
00C8BB  1               ; Operation:
00C8BB  1               ;   1. $E99A retrieves a pointer and returns its low byte in A.
00C8BB  1               ;   2. The high byte is read through ($00),Y.
00C8BB  1               ;   3. Each source record begins with a nonzero size/offset byte.
00C8BB  1               ;   4. The current source pointer is written to $0400,X as a low/high pair.
00C8BB  1               ;   5. The source pointer advances by (record byte * 4) + carry adjustment.
00C8BB  1               ;   6. A zero record byte terminates the list.
00C8BB  1               ;
00C8BB  1               ; Exit:
00C8BB  1               ;   Y = $04
00C8BB  1               ; ============================================================================
00C8BB  1               
00C8BB  1               ; ----------------------------------------------------------------------------
00C8BB  1               ; Contract:
00C8BB  1               ;   Description: Implements Expand Record Pointer List.
00C8BB  1               ;   Entry: Registers: A, X; Memory: (indirectptrlo), (recordptrlo), recordptrlo, recordptrhi
00C8BB  1               ;   Returns/products: Registers/clobbers: A, X, Y
00C8BB  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00C8BB  1               ;   Memory effects: recordptrlo, recordptrhi, $0400
00C8BB  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00C8BB  1               ;          comparison, load, or store path and are not a stable API product.
00C8BB  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 5.
00C8BB  1               ; ----------------------------------------------------------------------------
00C8BB  1               ExpandRecordPointerList:        ; $C8BB
00C8BB  1  20 9A E9         jsr DecodeInlineParameters                   ; $C8BB: 20 9A E9
00C8BE  1               
00C8BE  1  85 02            sta RecordPtrLo             ; $C8BE: 85 02
00C8C0  1                                               ; Save source pointer low byte.
00C8C0  1               
00C8C0  1  B1 00            lda (IndirectPtrLo),y       ; $C8C0: B1 00
00C8C2  1  85 03            sta RecordPtrHi             ; $C8C2: 85 03
00C8C4  1                                               ; Save source pointer high byte.
00C8C4  1               
00C8C4  1  A0 00            ldy #$00                    ; $C8C4: A0 00
00C8C6  1               
00C8C6  1               ; ----------------------------------------------------------------------------
00C8C6  1               ; Read the next record byte through pointer $02/$03.
00C8C6  1               ; A zero byte terminates the list.
00C8C6  1               ; ----------------------------------------------------------------------------
00C8C6  1               
00C8C6  1               Routine_C8C6_ReadRecord:        ; $C8C6
00C8C6  1  B1 02            lda (RecordPtrLo),y         ; $C8C6: B1 02
00C8C8  1  F0 1B            beq Routine_C8E5_Done       ; $C8C8: F0 1B
00C8CA  1               
00C8CA  1               ; ----------------------------------------------------------------------------
00C8CA  1               ; Store the current source pointer into the destination table.
00C8CA  1               ; Each destination entry is a two-byte pointer.
00C8CA  1               ; ----------------------------------------------------------------------------
00C8CA  1               
00C8CA  1  A5 02            lda RecordPtrLo             ; $C8CA: A5 02
00C8CC  1  9D 00 04         sta $0400,x                 ; $C8CC: 9D 00 04
00C8CF  1  E8               inx                         ; $C8CF: E8
00C8D0  1               
00C8D0  1  A5 03            lda RecordPtrHi             ; $C8D0: A5 03
00C8D2  1  9D 00 04         sta $0400,x                 ; $C8D2: 9D 00 04
00C8D5  1  E8               inx                         ; $C8D5: E8
00C8D6  1               
00C8D6  1               ; ----------------------------------------------------------------------------
00C8D6  1               ; Advance the source pointer.
00C8D6  1               ;
00C8D6  1               ; Reload the record byte, multiply it by four, then add it to the pointer low
00C8D6  1               ; byte. SEC means the effective increment is:
00C8D6  1               ;
00C8D6  1               ;   (record byte * 4) + 1
00C8D6  1               ;
00C8D6  1               ; If the low-byte addition carries, increment the pointer high byte.
00C8D6  1               ; ----------------------------------------------------------------------------
00C8D6  1               
00C8D6  1  B1 02            lda (RecordPtrLo),y         ; $C8D6: B1 02
00C8D8  1  0A               asl                         ; $C8D8: 0A
00C8D9  1  0A               asl                         ; $C8D9: 0A
00C8DA  1               
00C8DA  1  38               sec                         ; $C8DA: 38
00C8DB  1  65 02            adc RecordPtrLo             ; $C8DB: 65 02
00C8DD  1  85 02            sta RecordPtrLo             ; $C8DD: 85 02
00C8DF  1               
00C8DF  1  90 E5            bcc Routine_C8C6_ReadRecord ; $C8DF: 90 E5
00C8E1  1               
00C8E1  1  E6 03            inc RecordPtrHi             ; $C8E1: E6 03
00C8E3  1  B0 E1            bcs Routine_C8C6_ReadRecord ; $C8E3: B0 E1
00C8E5  1                                               ; Always taken because INC does not alter carry.
00C8E5  1               
00C8E5  1               ; ----------------------------------------------------------------------------
00C8E5  1               ; Return with Y = 4.
00C8E5  1               ; ----------------------------------------------------------------------------
00C8E5  1               
00C8E5  1               Routine_C8E5_Done:              ; $C8E5
00C8E5  1  A0 04            ldy #$04                    ; $C8E5: A0 04
00C8E7  1  60               rts                         ; $C8E7: 60
00C8E8  1               
00C8E8  1               ; ============================================================================
00C8E8  1               ; $C8E8-$C903
00C8E8  1               ; Initialize paired counters and random bitfields.
00C8E8  1               ;
00C8E8  1               ; For X = 1 and X = 0:
00C8E8  1               ;   $51,X is initialized to eight.
00C8E8  1               ;   Eight random carry bits are shifted into $4F,X.
00C8E8  1               ;   One additional random carry bit is shifted into $4D,X.
00C8E8  1               ; ============================================================================
00C8E8  1               
00C8E8  1               ; ----------------------------------------------------------------------------
00C8E8  1               ; Contract:
00C8E8  1               ;   Description: Initializes Random Bitfields.
00C8E8  1               ;   Entry: Registers: A, X, Y
00C8E8  1               ;   Returns/products: Registers/clobbers: A, X, Y
00C8E8  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00C8E8  1               ;   Memory effects: counter51
00C8E8  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00C8E8  1               ;          comparison, load, or store path and are not a stable API product.
00C8E8  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00C8E8  1               ; ----------------------------------------------------------------------------
00C8E8  1               InitializeRandomBitfields:                   ; $C8E8
00C8E8  1  A2 01            ldx #$01                    ; $C8E8: A2 01
00C8EA  1               
00C8EA  1               Routine_C8EA_NextEntry:         ; $C8EA
00C8EA  1  A0 08            ldy #$08                    ; $C8EA: A0 08
00C8EC  1               
00C8EC  1  98               tya                         ; $C8EC: 98
00C8ED  1  95 51            sta Counter51,x             ; $C8ED: 95 51
00C8EF  1               
00C8EF  1               Routine_C8EF_BuildRandomBits:   ; $C8EF
00C8EF  1  20 F5 E5         jsr AdvanceRandomState                   ; $C8EF: 20 F5 E5
00C8F2  1  C9 80            cmp #$80                    ; $C8F2: C9 80
00C8F4  1                                               ; Carry reflects whether random value >= $80.
00C8F4  1               
00C8F4  1  76 4F            ror RandomBits0,x           ; $C8F4: 76 4F
00C8F6  1                                               ; Shift the random carry bit into $4F,X.
00C8F6  1               
00C8F6  1  88               dey                         ; $C8F6: 88
00C8F7  1  D0 F6            bne Routine_C8EF_BuildRandomBits
00C8F9  1                                               ; $C8F7: D0 F6
00C8F9  1               
00C8F9  1  20 F5 E5         jsr AdvanceRandomState                   ; $C8F9: 20 F5 E5
00C8FC  1  C9 80            cmp #$80                    ; $C8FC: C9 80
00C8FE  1               
00C8FE  1  76 4D            ror RandomState0,x          ; $C8FE: 76 4D
00C900  1                                               ; Shift one random carry bit into $4D,X.
00C900  1               
00C900  1  CA               dex                         ; $C900: CA
00C901  1  10 E7            bpl Routine_C8EA_NextEntry  ; $C901: 10 E7
00C903  1               
00C903  1  60               rts                         ; $C903: 60
00C904  1               
00C904  1               ; ============================================================================
00C904  1               ; $C904-$C91A
00C904  1               ; Dispatch one of two inline records according to the sign of $4D,X.
00C904  1               ;
00C904  1               ; X is selected from the low bit of $33.
00C904  1               ; ============================================================================
00C904  1               
00C904  1               ; ----------------------------------------------------------------------------
00C904  1               ; Contract:
00C904  1               ;   Description: Queues Random State Record.
00C904  1               ;   Entry: Registers: A; Memory: roundstateindex, randomstate0
00C904  1               ;   Returns/products: Registers/clobbers: A, X
00C904  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00C904  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00C904  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00C904  1               ;          comparison, load, or store path and are not a stable API product.
00C904  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00C904  1               ; ----------------------------------------------------------------------------
00C904  1               QueueRandomStateRecord:                   ; $C904
00C904  1  A5 33            lda RoundStateIndex            ; $C904: A5 33
00C906  1  29 01            and #$01                    ; $C906: 29 01
00C908  1  AA               tax                         ; $C908: AA
00C909  1               
00C909  1  B5 4D            lda RandomState0,x          ; $C909: B5 4D
00C90B  1  30 07            bmi QueueAlternateRandomStateRecord   ; $C90B: 30 07
00C90D  1               
00C90D  1  20 BB C8         jsr ExpandRecordPointerList ; $C90D: 20 BB C8
00C910  1                   ; Inline pointer/record consumed by $C8BB.
00C910  1  0C B4 ED         .byte $0C,$B4,$ED           ; $C910-$C912
00C913  1               
00C913  1  60               rts                         ; $C913: 60
00C914  1               
00C914  1               QueueAlternateRandomStateRecord:          ; $C914
00C914  1  20 BB C8         jsr ExpandRecordPointerList ; $C914: 20 BB C8
00C917  1               
00C917  1                   ; Alternate inline pointer/record consumed by $C8BB.
00C917  1  0C 51 EC         .byte $0C,$51,$EC           ; $C917-$C919
00C91A  1               
00C91A  1  60               rts                         ; $C91A: 60
00C91B  1               
00C91B  1               ; ============================================================================
00C91B  1               ; $C91B-$C942
00C91B  1               ; Select and dispatch a record from the paired random state.
00C91B  1               ;
00C91B  1               ; The low bit of $33 selects X. $51,X determines how many times $4F,X is
00C91B  1               ; shifted right. If the selected carry is clear, the first record is used.
00C91B  1               ; If the carry is set, $4C is decremented and the second record is used.
00C91B  1               ; ============================================================================
00C91B  1               
00C91B  1               ; ----------------------------------------------------------------------------
00C91B  1               ; Contract:
00C91B  1               ;   Description: Queues Random Direction Record.
00C91B  1               ;   Entry: Registers: A, Y; Memory: roundstateindex, counter51, randombits0, randomstate0
00C91B  1               ;   Returns/products: Registers/clobbers: A, X, Y
00C91B  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00C91B  1               ;   Memory effects: horizontaldirectionmask
00C91B  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00C91B  1               ;          comparison, load, or store path and are not a stable API product.
00C91B  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00C91B  1               ; ----------------------------------------------------------------------------
00C91B  1               QueueRandomDirectionRecord:                   ; $C91B
00C91B  1  A5 33            lda RoundStateIndex            ; $C91B: A5 33
00C91D  1  29 01            and #$01                    ; $C91D: 29 01
00C91F  1  AA               tax                         ; $C91F: AA
00C920  1               
00C920  1  B4 51            ldy Counter51,x             ; $C920: B4 51
00C922  1  F0 08            beq UseRandomDirectionSignBit ; $C922: F0 08
00C924  1               
00C924  1  B5 4F            lda RandomBits0,x           ; $C924: B5 4F
00C926  1               
00C926  1               SelectRandomDirectionBit:    ; $C926
00C926  1  4A               lsr                         ; $C926: 4A
00C927  1               
00C927  1  88               dey                         ; $C927: 88
00C928  1  D0 FC            bne SelectRandomDirectionBit
00C92A  1                                               ; $C928: D0 FC
00C92A  1               
00C92A  1  F0 03            beq SaveDirectionSelection  ; $C92A: F0 03
00C92C  1                                               ; Always taken because Y is zero.
00C92C  1                                               ; Carry from the final LSR is preserved.
00C92C  1               
00C92C  1               UseRandomDirectionSignBit:        ; $C92C
00C92C  1  B5 4D            lda RandomState0,x          ; $C92C: B5 4D
00C92E  1  0A               asl                         ; $C92E: 0A
00C92F  1                                               ; Move bit 7 into carry.
00C92F  1               
00C92F  1               SaveDirectionSelection:         ; $C92F
00C92F  1  84 4C            sty HorizontalDirectionMask           ; $C92F: 84 4C
00C931  1               
00C931  1  B0 07            bcs QueueAlternateDirectionRecord  ; $C931: B0 07
00C933  1               
00C933  1  20 BB C8         jsr ExpandRecordPointerList ; $C933: 20 BB C8
00C936  1               
00C936  1                   ; Inline pointer/record consumed by $C8BB.
00C936  1  00 39 ED         .byte $00,$39,$ED           ; $C936-$C938
00C939  1               
00C939  1  60               rts                         ; $C939: 60
00C93A  1               
00C93A  1               QueueAlternateDirectionRecord:         ; $C93A
00C93A  1  C6 4C            dec HorizontalDirectionMask           ; $C93A: C6 4C
00C93C  1               
00C93C  1  20 BB C8         jsr ExpandRecordPointerList ; $C93C: 20 BB C8
00C93F  1               
00C93F  1                   ; Alternate inline pointer/record consumed by $C8BB.
00C93F  1  00 D6 EB         .byte $00,$D6,$EB           ; $C93F-$C941
00C942  1               
00C942  1  60               rts                         ; $C942: 60
00C943  1               
00C943  1               
00C943  1               
00C943  1               ; ============================================================================
00C943  1               ; $C943-$C94E
00C943  1               ; Clear the base entries of three object-field arrays.
00C943  1               ; ============================================================================
00C943  1               
00C943  1               ; ----------------------------------------------------------------------------
00C943  1               ; Contract:
00C943  1               ;   Description: Clears or resets Base Acceleration Fields.
00C943  1               ;   Entry: Registers: A
00C943  1               ;   Returns/products: Registers/clobbers: A
00C943  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00C943  1               ;   Memory effects: $0506, $0537, $0568
00C943  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00C943  1               ;          comparison, load, or store path and are not a stable API product.
00C943  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 6.
00C943  1               ; ----------------------------------------------------------------------------
00C943  1               ClearBaseAccelerationFields:                   ; $C943
00C943  1  A9 00            lda #$00                    ; $C943: A9 00
00C945  1               
00C945  1  8D 06 05         sta $0506                   ; $C945: 8D 06 05
00C948  1  8D 37 05         sta $0537                   ; $C948: 8D 37 05
00C94B  1  8D 68 05         sta $0568                   ; $C94B: 8D 68 05
00C94E  1               
00C94E  1  60               rts                         ; $C94E: 60
00C94F  1               
00C94F  1               ; ============================================================================
00C94F  1               ; $C94F-$C958
00C94F  1               ; Initialize the fields at $0509/$050A, $053A/$053B, and $056B/$056C
00C94F  1               ; with six inline zero bytes.
00C94F  1               ;
00C94F  1               ; Routine $C985 retrieves the address of the inline data and consumes all
00C94F  1               ; six bytes.
00C94F  1               ; ============================================================================
00C94F  1               
00C94F  1               ; ----------------------------------------------------------------------------
00C94F  1               ; Contract:
00C94F  1               ;   Description: Clears or resets Base Position Fields.
00C94F  1               ;   Entry: No register input inferred
00C94F  1               ;   Returns/products: No direct product inferred
00C94F  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00C94F  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00C94F  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00C94F  1               ;          comparison, load, or store path and are not a stable API product.
00C94F  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 6.
00C94F  1               ; ----------------------------------------------------------------------------
00C94F  1               ClearBasePositionFields:                   ; $C94F
00C94F  1  20 85 C9         jsr LoadBaseMotionFieldsInline ; $C94F: 20 85 C9
00C952  1               
00C952  1  00 00            .word $0000                 ; $C952-$C953
00C954  1  00 00            .word $0000                 ; $C954-$C955
00C956  1  00 00            .word $0000                 ; $C956-$C957
00C958  1               
00C958  1  60               rts                         ; $C958: 60
00C959  1               
00C959  1               ; ============================================================================
00C959  1               ; $C959-$C962
00C959  1               ; Initialize the fields at $0507/$0508, $0538/$0539, and $0569/$056A
00C959  1               ; with six inline zero bytes.
00C959  1               ;
00C959  1               ; Routine $C963 retrieves the address of the inline data and consumes all
00C959  1               ; six bytes.
00C959  1               ; ============================================================================
00C959  1               
00C959  1               ClearBaseMotionFields:                   ; $C959
00C959  1  20 63 C9         jsr LoadBasePositionFieldsInline ; $C959: 20 63 C9
00C95C  1               
00C95C  1  00 00            .word $0000                 ; $C95C-$C95D
00C95E  1  00 00            .word $0000                 ; $C95E-$C95F
00C960  1  00 00            .word $0000                 ; $C960-$C961
00C962  1               
00C962  1  60               rts                         ; $C962: 60
00C963  1               
00C963  1               ; ============================================================================
00C963  1               ; $C963-$C984
00C963  1               ; Load three 16-bit field values from inline data.
00C963  1               ;
00C963  1               ; $E99A retrieves the inline-data pointer:
00C963  1               ;   X = first byte
00C963  1               ;   A = second byte
00C963  1               ;   $00/$01 points to the remaining bytes
00C963  1               ;
00C963  1               ; The six input bytes are stored as:
00C963  1               ;
00C963  1               ;   byte 0 -> $0507
00C963  1               ;   byte 1 -> $0508
00C963  1               ;   byte 2 -> $0538
00C963  1               ;   byte 3 -> $0539
00C963  1               ;   byte 4 -> $0569
00C963  1               ;   byte 5 -> $056A
00C963  1               ;
00C963  1               ; Exit:
00C963  1               ;   Y = $04
00C963  1               ; ============================================================================
00C963  1               ; ============================================================================
00C963  1               ; $C963-$C984
00C963  1               ; Load the $09/$0A, $3A/$3B, and $6B/$6C field group.
00C963  1               ; ============================================================================
00C963  1               
00C963  1               ; ----------------------------------------------------------------------------
00C963  1               ; Contract:
00C963  1               ;   Description: Implements Load Base Position Fields Inline.
00C963  1               ;   Entry: Registers: A, X, Y; Memory: (indirectptrlo)
00C963  1               ;   Returns/products: Registers/clobbers: A, Y
00C963  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00C963  1               ;   Memory effects: $0509, $050a, $053a, $053b, $056b, $056c
00C963  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00C963  1               ;          comparison, load, or store path and are not a stable API product.
00C963  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 2.
00C963  1               ; ----------------------------------------------------------------------------
00C963  1               LoadBasePositionFieldsInline:        ; $C963
00C963  1  20 9A E9         jsr DecodeInlineParameters                   ; $C963: 20 9A E9
00C966  1               
00C966  1  8E 09 05         stx $0509                   ; $C966: 8E 09 05
00C969  1  8D 0A 05         sta $050A                   ; $C969: 8D 0A 05
00C96C  1               
00C96C  1  B1 00            lda (IndirectPtrLo),y       ; $C96C: B1 00
00C96E  1  8D 3A 05         sta $053A                   ; $C96E: 8D 3A 05
00C971  1               
00C971  1  C8               iny                         ; $C971: C8
00C972  1               
00C972  1  B1 00            lda (IndirectPtrLo),y       ; $C972: B1 00
00C974  1  8D 3B 05         sta $053B                   ; $C974: 8D 3B 05
00C977  1               
00C977  1  C8               iny                         ; $C977: C8
00C978  1               
00C978  1  B1 00            lda (IndirectPtrLo),y       ; $C978: B1 00
00C97A  1  8D 6B 05         sta $056B                   ; $C97A: 8D 6B 05
00C97D  1               
00C97D  1  C8               iny                         ; $C97D: C8
00C97E  1               
00C97E  1  B1 00            lda (IndirectPtrLo),y       ; $C97E: B1 00
00C980  1  8D 6C 05         sta $056C                   ; $C980: 8D 6C 05
00C983  1               
00C983  1  C8               iny                         ; $C983: C8
00C984  1  60               rts                         ; $C984: 60
00C985  1               
00C985  1               ; ============================================================================
00C985  1               ; $C985-$C9A6
00C985  1               ; Load the $07/$08, $38/$39, and $69/$6A field group.
00C985  1               ; ============================================================================
00C985  1               
00C985  1               ; ----------------------------------------------------------------------------
00C985  1               ; Contract:
00C985  1               ;   Description: Implements Load Base Motion Fields Inline.
00C985  1               ;   Entry: Registers: A, X, Y; Memory: (indirectptrlo)
00C985  1               ;   Returns/products: Registers/clobbers: A, Y
00C985  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00C985  1               ;   Memory effects: $0507, $0508, $0538, $0539, $0569, $056a
00C985  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00C985  1               ;          comparison, load, or store path and are not a stable API product.
00C985  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00C985  1               ; ----------------------------------------------------------------------------
00C985  1               LoadBaseMotionFieldsInline:        ; $C985
00C985  1  20 9A E9         jsr DecodeInlineParameters                   ; $C985: 20 9A E9
00C988  1               
00C988  1  8E 07 05         stx $0507                   ; $C988: 8E 07 05
00C98B  1  8D 08 05         sta $0508                   ; $C98B: 8D 08 05
00C98E  1               
00C98E  1  B1 00            lda (IndirectPtrLo),y       ; $C98E: B1 00
00C990  1  8D 38 05         sta $0538                   ; $C990: 8D 38 05
00C993  1               
00C993  1  C8               iny                         ; $C993: C8
00C994  1               
00C994  1  B1 00            lda (IndirectPtrLo),y       ; $C994: B1 00
00C996  1  8D 39 05         sta $0539                   ; $C996: 8D 39 05
00C999  1               
00C999  1  C8               iny                         ; $C999: C8
00C99A  1               
00C99A  1  B1 00            lda (IndirectPtrLo),y       ; $C99A: B1 00
00C99C  1  8D 69 05         sta $0569                   ; $C99C: 8D 69 05
00C99F  1               
00C99F  1  C8               iny                         ; $C99F: C8
00C9A0  1               
00C9A0  1  B1 00            lda (IndirectPtrLo),y       ; $C9A0: B1 00
00C9A2  1  8D 6A 05         sta $056A                   ; $C9A2: 8D 6A 05
00C9A5  1               
00C9A5  1  C8               iny                         ; $C9A5: C8
00C9A6  1  60               rts                         ; $C9A6: 60
00C9A7  1               
00C9A7  1               ; ============================================================================
00C9A7  1               ; $C9A7-$C9BF
00C9A7  1               ; Load two indexed 16-bit field values from inline data.
00C9A7  1               ;
00C9A7  1               ; Entry:
00C9A7  1               ;   X = object-array offset
00C9A7  1               ;
00C9A7  1               ; The four input bytes are stored as:
00C9A7  1               ;
00C9A7  1               ;   byte 0 -> $0509,X
00C9A7  1               ;   byte 1 -> $050A,X
00C9A7  1               ;   byte 2 -> $053A,X
00C9A7  1               ;   byte 3 -> $053B,X
00C9A7  1               ;
00C9A7  1               ; Exit:
00C9A7  1               ;   Y = $02
00C9A7  1               ; ============================================================================
00C9A7  1               
00C9A7  1               LoadObjectPositionInline: ; $C9A7
00C9A7  1  20 9A E9         jsr DecodeInlineParameters                   ; $C9A7: 20 9A E9
00C9AA  1               
00C9AA  1  9D 09 05         sta $0509,x                 ; $C9AA: 9D 09 05
00C9AD  1               
00C9AD  1  B1 00            lda (IndirectPtrLo),y       ; $C9AD: B1 00
00C9AF  1  9D 0A 05         sta $050A,x                 ; $C9AF: 9D 0A 05
00C9B2  1               
00C9B2  1  C8               iny                         ; $C9B2: C8
00C9B3  1               
00C9B3  1  B1 00            lda (IndirectPtrLo),y       ; $C9B3: B1 00
00C9B5  1  9D 3A 05         sta $053A,x                 ; $C9B5: 9D 3A 05
00C9B8  1               
00C9B8  1  C8               iny                         ; $C9B8: C8
00C9B9  1               
00C9B9  1  B1 00            lda (IndirectPtrLo),y       ; $C9B9: B1 00
00C9BB  1  9D 3B 05         sta $053B,x                 ; $C9BB: 9D 3B 05
00C9BE  1               
00C9BE  1  C8               iny                         ; $C9BE: C8
00C9BF  1  60               rts                         ; $C9BF: 60
00C9C0  1               
00C9C0  1               ; ============================================================================
00C9C0  1               ; $C9C0-$CA22
00C9C0  1               ; Compare an indexed object's position against the base object's position.
00C9C0  1               ;
00C9C0  1               ; Entry:
00C9C0  1               ;   X = indexed object-array offset
00C9C0  1               ;
00C9C0  1               ; Return:
00C9C0  1               ;   A = $00 when the comparison succeeds and state is updated
00C9C0  1               ;   A = $01 when any comparison fails
00C9C0  1               ;
00C9C0  1               ; The routine performs three checks:
00C9C0  1               ;   1. $056B/$056C must be less than three.
00C9C0  1               ;   2. The horizontal distance must satisfy the signed threshold test.
00C9C0  1               ;   3. The vertical distance must satisfy the signed threshold test.
00C9C0  1               ; ============================================================================
00C9C0  1               
00C9C0  1               ; ----------------------------------------------------------------------------
00C9C0  1               ; Contract:
00C9C0  1               ;   Description: Implements Try Merge Object Into Base.
00C9C0  1               ;   Entry: Registers: A, Y; Memory: $056b, $056c, $0509, $050a, $053a
00C9C0  1               ;   Returns/products: Registers/clobbers: A, Y
00C9C0  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00C9C0  1               ;   Memory effects: $050a, $053b, $056c, $056d, $056e, basemotionactive
00C9C0  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00C9C0  1               ;          comparison, load, or store path and are not a stable API product.
00C9C0  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 3.
00C9C0  1               ; ----------------------------------------------------------------------------
00C9C0  1               TryMergeObjectIntoBase:                   ; $C9C0
00C9C0  1  AD 6B 05         lda $056B                   ; $C9C0: AD 6B 05
00C9C3  1  C9 00            cmp #$00                    ; $C9C3: C9 00
00C9C5  1               
00C9C5  1  AD 6C 05         lda $056C                   ; $C9C5: AD 6C 05
00C9C8  1  E9 03            sbc #$03                    ; $C9C8: E9 03
00C9CA  1                                               ; Carry from CMP #$00 participates in this
00C9CA  1                                               ; subtraction because LDA does not alter carry.
00C9CA  1               
00C9CA  1  10 54            bpl ObjectMergeFailed     ; $C9CA: 10 54
00C9CC  1               
00C9CC  1               ; ----------------------------------------------------------------------------
00C9CC  1               ; Calculate the signed difference between the base horizontal position and
00C9CC  1               ; the indexed object's horizontal position:
00C9CC  1               ;
00C9CC  1               ;   base:    $0509/$050A
00C9CC  1               ;   indexed: $0509,X/$050A,X
00C9CC  1               ;
00C9CC  1               ; The low-byte difference is passed in Y and the high-byte difference in A
00C9CC  1               ; to the helper at $E7CB.
00C9CC  1               ; ----------------------------------------------------------------------------
00C9CC  1               
00C9CC  1  38               sec                         ; $C9CC: 38
00C9CD  1               
00C9CD  1  AD 09 05         lda $0509                   ; $C9CD: AD 09 05
00C9D0  1  FD 09 05         sbc $0509,x                 ; $C9D0: FD 09 05
00C9D3  1  A8               tay                         ; $C9D3: A8
00C9D4  1               
00C9D4  1  AD 0A 05         lda $050A                   ; $C9D4: AD 0A 05
00C9D7  1  FD 0A 05         sbc $050A,x                 ; $C9D7: FD 0A 05
00C9DA  1               
00C9DA  1  20 CB E7         jsr AbsoluteValueAY                   ; $C9DA: 20 CB E7
00C9DD  1               
00C9DD  1               ; ----------------------------------------------------------------------------
00C9DD  1               ; Test the normalized horizontal result.
00C9DD  1               ;
00C9DD  1               ; CPY #$80 establishes carry for the following SBC #$00. This effectively
00C9DD  1               ; includes Y's sign/high-bit state in the signed comparison.
00C9DD  1               ; ----------------------------------------------------------------------------
00C9DD  1               
00C9DD  1  C0 80            cpy #$80                    ; $C9DD: C0 80
00C9DF  1  E9 00            sbc #$00                    ; $C9DF: E9 00
00C9E1  1               
00C9E1  1  10 3D            bpl ObjectMergeFailed     ; $C9E1: 10 3D
00C9E3  1               
00C9E3  1               ; ----------------------------------------------------------------------------
00C9E3  1               ; Repeat the same signed-distance calculation for the vertical position:
00C9E3  1               ;
00C9E3  1               ;   base:    $053A/$053B
00C9E3  1               ;   indexed: $053A,X/$053B,X
00C9E3  1               ; ----------------------------------------------------------------------------
00C9E3  1               
00C9E3  1  38               sec                         ; $C9E3: 38
00C9E4  1               
00C9E4  1  AD 3A 05         lda $053A                   ; $C9E4: AD 3A 05
00C9E7  1  FD 3A 05         sbc $053A,x                 ; $C9E7: FD 3A 05
00C9EA  1  A8               tay                         ; $C9EA: A8
00C9EB  1               
00C9EB  1  AD 3B 05         lda $053B                   ; $C9EB: AD 3B 05
00C9EE  1  FD 3B 05         sbc $053B,x                 ; $C9EE: FD 3B 05
00C9F1  1               
00C9F1  1  20 CB E7         jsr AbsoluteValueAY                   ; $C9F1: 20 CB E7
00C9F4  1               
00C9F4  1  C0 80            cpy #$80                    ; $C9F4: C0 80
00C9F6  1  E9 00            sbc #$00                    ; $C9F6: E9 00
00C9F8  1               
00C9F8  1  10 26            bpl ObjectMergeFailed     ; $C9F8: 10 26
00C9FA  1               
00C9FA  1               ; ----------------------------------------------------------------------------
00C9FA  1               ; The indexed object passed all comparisons.
00C9FA  1               ;
00C9FA  1               ; Copy its high position bytes into the base object, set $056C to one,
00C9FA  1               ; clear the indexed object's values at $056D/$056E, and reset shared fields.
00C9FA  1               ; ----------------------------------------------------------------------------
00C9FA  1               
00C9FA  1  BD 0A 05         lda $050A,x                 ; $C9FA: BD 0A 05
00C9FD  1  8D 0A 05         sta $050A                   ; $C9FD: 8D 0A 05
00CA00  1               
00CA00  1  BD 3B 05         lda $053B,x                 ; $CA00: BD 3B 05
00CA03  1  8D 3B 05         sta $053B                   ; $CA03: 8D 3B 05
00CA06  1               
00CA06  1  A9 01            lda #$01                    ; $CA06: A9 01
00CA08  1  8D 6C 05         sta $056C                   ; $CA08: 8D 6C 05
00CA0B  1               
00CA0B  1  A9 00            lda #$00                    ; $CA0B: A9 00
00CA0D  1  9D 6D 05         sta $056D,x                 ; $CA0D: 9D 6D 05
00CA10  1  9D 6E 05         sta $056E,x                 ; $CA10: 9D 6E 05
00CA13  1               
00CA13  1  20 43 C9         jsr ClearBaseAccelerationFields            ; $CA13: 20 43 C9
00CA16  1  20 4F C9         jsr ClearBasePositionFields            ; $CA16: 20 4F C9
00CA19  1               
00CA19  1  E6 5E            inc BaseMotionEventCount        ; $CA19: E6 5E
00CA1B  1               
00CA1B  1  A9 00            lda #$00                    ; $CA1B: A9 00
00CA1D  1  85 5C            sta BaseMotionActive            ; $CA1D: 85 5C
00CA1F  1               
00CA1F  1  60               rts                         ; $CA1F: 60
00CA20  1                                               ; Return A = $00.
00CA20  1               
00CA20  1               ; ----------------------------------------------------------------------------
00CA20  1               ; Comparison failed.
00CA20  1               ; ----------------------------------------------------------------------------
00CA20  1               
00CA20  1               ObjectMergeFailed:            ; $CA20
00CA20  1  A9 01            lda #$01                    ; $CA20: A9 01
00CA22  1  60               rts                         ; $CA22: 60
00CA23  1               
00CA23  1               ; ============================================================================
00CA23  1               ; $CA23-$CA4B
00CA23  1               ; Initialize base movement and position fields.
00CA23  1               ;
00CA23  1               ; The routine has a secondary entry point at $CA2A. The primary entry at
00CA23  1               ; $CA23 clears $056A and branches directly to $CA2F because A is zero.
00CA23  1               ;
00CA23  1               ; Entry at $CA2A:
00CA23  1               ;   A is stored into $056A before continuing.
00CA23  1               ;
00CA23  1               ; Inputs preserved into object fields:
00CA23  1               ;   X -> $0508
00CA23  1               ;   Y -> $0539
00CA23  1               ;
00CA23  1               ; Exit:
00CA23  1               ;   $5C is incremented.
00CA23  1               ; ============================================================================
00CA23  1               
00CA23  1               ; ----------------------------------------------------------------------------
00CA23  1               ; Contract:
00CA23  1               ;   Description: Initializes Base Motion Zero.
00CA23  1               ;   Entry: Registers: A, X, Y
00CA23  1               ;   Returns/products: Registers/clobbers: A
00CA23  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00CA23  1               ;   Memory effects: $056a, $0568, $0508, $0539, $0507, $0538, $0569
00CA23  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00CA23  1               ;          comparison, load, or store path and are not a stable API product.
00CA23  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00CA23  1               ; ----------------------------------------------------------------------------
00CA23  1               InitializeBaseMotionZero:                   ; $CA23
00CA23  1  A9 00            lda #$00                    ; $CA23: A9 00
00CA25  1  8D 6A 05         sta $056A                   ; $CA25: 8D 6A 05
00CA28  1               
00CA28  1  F0 05            beq StoreBaseMotionInitialization
00CA2A  1                                               ; $CA28: F0 05
00CA2A  1                                               ; Always taken because A is zero.
00CA2A  1               
00CA2A  1               ; ----------------------------------------------------------------------------
00CA2A  1               ; Alternate entry point.
00CA2A  1               ;
00CA2A  1               ; Callers entering at $CA2A can provide a nonzero value in A for $056A.
00CA2A  1               ; ----------------------------------------------------------------------------
00CA2A  1               
00CA2A  1               ; ----------------------------------------------------------------------------
00CA2A  1               ; Contract:
00CA2A  1               ;   Description: Initializes Base Motion.
00CA2A  1               ;   Entry: Registers: A, X, Y
00CA2A  1               ;   Returns/products: Registers/clobbers: A
00CA2A  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00CA2A  1               ;   Memory effects: $056a, $0568, $0508, $0539, $0507, $0538, $0569, $0506
00CA2A  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00CA2A  1               ;          comparison, load, or store path and are not a stable API product.
00CA2A  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00CA2A  1               ; ----------------------------------------------------------------------------
00CA2A  1               InitializeBaseMotion:                   ; $CA2A
00CA2A  1  8D 6A 05         sta $056A                   ; $CA2A: 8D 6A 05
00CA2D  1               
00CA2D  1  A9 FF            lda #$FF                    ; $CA2D: A9 FF
00CA2F  1               
00CA2F  1               ; ----------------------------------------------------------------------------
00CA2F  1               ; Mark the base entry at $0568 and store the supplied X/Y field values.
00CA2F  1               ;
00CA2F  1               ; Primary entry stores $00 at $0568 because it branches directly here with
00CA2F  1               ; A equal to zero. Alternate entry stores $FF.
00CA2F  1               ; ----------------------------------------------------------------------------
00CA2F  1               
00CA2F  1               StoreBaseMotionInitialization:       ; $CA2F
00CA2F  1  8D 68 05         sta $0568                   ; $CA2F: 8D 68 05
00CA32  1               
00CA32  1  8E 08 05         stx $0508                   ; $CA32: 8E 08 05
00CA35  1  8C 39 05         sty $0539                   ; $CA35: 8C 39 05
00CA38  1               
00CA38  1               ; ----------------------------------------------------------------------------
00CA38  1               ; Clear the remaining base position and movement fields.
00CA38  1               ; ----------------------------------------------------------------------------
00CA38  1               
00CA38  1  A9 00            lda #$00                    ; $CA38: A9 00
00CA3A  1               
00CA3A  1  8D 07 05         sta $0507                   ; $CA3A: 8D 07 05
00CA3D  1  8D 38 05         sta $0538                   ; $CA3D: 8D 38 05
00CA40  1  8D 69 05         sta $0569                   ; $CA40: 8D 69 05
00CA43  1               
00CA43  1  8D 06 05         sta $0506                   ; $CA43: 8D 06 05
00CA46  1  8D 37 05         sta $0537                   ; $CA46: 8D 37 05
00CA49  1               
00CA49  1  E6 5C            inc BaseMotionActive                     ; $CA49: E6 5C
00CA4B  1               
00CA4B  1  60               rts                         ; $CA4B: 60
00CA4C  1               
00CA4C  1               ; ============================================================================
00CA4C  1               ; $CA4C-$CAD1
00CA4C  1               ; State progression and trajectory/update loop
00CA4C  1               ; ============================================================================
00CA4C  1               
00CA4C  1               RunBaseTrajectorySequence:                   ; $CA4C
00CA4C  1  A5 5D            lda BaseMotionPhase             ; $CA4C: A5 5D
00CA4E  1  D0 04            bne AdvanceTrajectoryPhase
00CA50  1                                               ; $CA4E: D0 04
00CA50  1               
00CA50  1  A9 40            lda #$40                    ; $CA50: A9 40
00CA52  1  85 FE            sta PendingAudioFlags             ; $CA52: 85 FE
00CA54  1               
00CA54  1               AdvanceTrajectoryPhase:      ; $CA54
00CA54  1  E6 5D            inc BaseMotionPhase             ; $CA54: E6 5D
00CA56  1               
00CA56  1               ; ----------------------------------------------------------------------------
00CA56  1               ; When the vertical high byte is nonnegative, derive new signed movement
00CA56  1               ; values from the current position fields.
00CA56  1               ; ----------------------------------------------------------------------------
00CA56  1               
00CA56  1  AD 3B 05         lda $053B                   ; $CA56: AD 3B 05
00CA59  1  30 1C            bmi UpdateTrajectoryFrame  ; $CA59: 30 1C
00CA5B  1               
00CA5B  1               ; ----------------------------------------------------------------------------
00CA5B  1               ; Derive $0508 from the negated high position at $050A.
00CA5B  1               ;
00CA5B  1               ; CMP #$80 followed by ROR is used twice to perform sign-aware shifting.
00CA5B  1               ; ----------------------------------------------------------------------------
00CA5B  1               
00CA5B  1  A9 00            lda #$00                    ; $CA5B: A9 00
00CA5D  1  38               sec                         ; $CA5D: 38
00CA5E  1  ED 0A 05         sbc $050A                   ; $CA5E: ED 0A 05
00CA61  1               
00CA61  1  C9 80            cmp #$80                    ; $CA61: C9 80
00CA63  1  6A               ror                         ; $CA63: 6A
00CA64  1               
00CA64  1  C9 80            cmp #$80                    ; $CA64: C9 80
00CA66  1  6A               ror                         ; $CA66: 6A
00CA67  1               
00CA67  1  8D 08 05         sta $0508                   ; $CA67: 8D 08 05
00CA6A  1               
00CA6A  1               ; ----------------------------------------------------------------------------
00CA6A  1               ; Derive $0539 from $053B.
00CA6A  1               ; ----------------------------------------------------------------------------
00CA6A  1               
00CA6A  1  A9 07            lda #$07                    ; $CA6A: A9 07
00CA6C  1  38               sec                         ; $CA6C: 38
00CA6D  1  ED 3B 05         sbc $053B                   ; $CA6D: ED 3B 05
00CA70  1               
00CA70  1  4A               lsr                         ; $CA70: 4A
00CA71  1  4A               lsr                         ; $CA71: 4A
00CA72  1               
00CA72  1  09 C0            ora #$C0                    ; $CA72: 09 C0
00CA74  1  8D 39 05         sta $0539                   ; $CA74: 8D 39 05
00CA77  1               
00CA77  1               ; ----------------------------------------------------------------------------
00CA77  1               ; Wait for a frame, then call $CBEC repeatedly until it returns carry set.
00CA77  1               ; ----------------------------------------------------------------------------
00CA77  1               
00CA77  1               UpdateTrajectoryFrame:         ; $CA77
00CA77  1  20 48 EB         jsr SelectObjectEventBank1                   ; $CA77: 20 48 EB
00CA7A  1               
00CA7A  1  A2 00            ldx #$00                    ; $CA7A: A2 00
00CA7C  1  20 EC CB         jsr TestObjectCollision                   ; $CA7C: 20 EC CB
00CA7F  1  90 F6            bcc UpdateTrajectoryFrame  ; $CA7F: 90 F6
00CA81  1               
00CA81  1  20 D2 CA         jsr EvaluateTrajectoryResult                   ; $CA81: 20 D2 CA
00CA84  1               
00CA84  1               ; ----------------------------------------------------------------------------
00CA84  1               ; Continue the state loop until $056C reaches at least three.
00CA84  1               ; ----------------------------------------------------------------------------
00CA84  1               
00CA84  1  AD 6C 05         lda $056C                   ; $CA84: AD 6C 05
00CA87  1  C9 03            cmp #$03                    ; $CA87: C9 03
00CA89  1  90 C1            bcc RunBaseTrajectorySequence            ; $CA89: 90 C1
00CA8B  1               
00CA8B  1               ; ----------------------------------------------------------------------------
00CA8B  1               ; Select one of three inline command records.
00CA8B  1               ; ----------------------------------------------------------------------------
00CA8B  1               
00CA8B  1  A5 5F            lda TrajectoryResult            ; $CA8B: A5 5F
00CA8D  1  30 21            bmi WaitForTrajectoryLimit
00CA8F  1                                               ; $CA8D: 30 21
00CA8F  1               
00CA8F  1  A5 5D            lda BaseMotionPhase             ; $CA8F: A5 5D
00CA91  1  D0 17            bne QueueLaterTrajectoryCommand  ; $CA91: D0 17
00CA93  1               
00CA93  1  AD 0A 05         lda $050A                   ; $CA93: AD 0A 05
00CA96  1  30 09            bmi QueueNegativeTrajectoryCommand  ; $CA96: 30 09
00CA98  1               
00CA98  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $CA98: 20 0A EB
00CA9B  1               
00CA9B  1                   ; Inline command record consumed by QueueInlineObjectEvent.
00CA9B  1  24 A3 CD         .byte $24,$A3,$CD           ; $CA9B-$CA9D
00CA9E  1               
00CA9E  1  4C B0 CA         jmp WaitForTrajectoryLimit
00CAA1  1                                               ; $CA9E: 4C B0 CA
00CAA1  1               
00CAA1  1               QueueNegativeTrajectoryCommand:         ; $CAA1
00CAA1  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $CAA1: 20 0A EB
00CAA4  1               
00CAA4  1                   ; Inline command record consumed by QueueInlineObjectEvent.
00CAA4  1  26 A3 CD         .byte $26,$A3,$CD           ; $CAA4-$CAA6
00CAA7  1               
00CAA7  1  4C B0 CA         jmp WaitForTrajectoryLimit
00CAAA  1                                               ; $CAA7: 4C B0 CA
00CAAA  1               
00CAAA  1               QueueLaterTrajectoryCommand:         ; $CAAA
00CAAA  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $CAAA: 20 0A EB
00CAAD  1               
00CAAD  1                   ; Inline command record consumed by QueueInlineObjectEvent.
00CAAD  1  1A 97 CD         .byte $1A,$97,$CD           ; $CAAD-$CAAF
00CAB0  1               
00CAB0  1               ; ----------------------------------------------------------------------------
00CAB0  1               ; Wait until the value derived by $CBEC reaches either:
00CAB0  1               ;
00CAB0  1               ;   $056C or greater, or
00CAB0  1               ;   at least $50.
00CAB0  1               ;
00CAB0  1               ; The returned A value is reduced by $38 and saved in $056E.
00CAB0  1               ; ----------------------------------------------------------------------------
00CAB0  1               
00CAB0  1               WaitForTrajectoryLimit:      ; $CAB0
00CAB0  1  20 48 EB         jsr SelectObjectEventBank1                   ; $CAB0: 20 48 EB
00CAB3  1               
00CAB3  1  A2 00            ldx #$00                    ; $CAB3: A2 00
00CAB5  1  20 EC CB         jsr TestObjectCollision                   ; $CAB5: 20 EC CB
00CAB8  1               
00CAB8  1  38               sec                         ; $CAB8: 38
00CAB9  1  E9 38            sbc #$38                    ; $CAB9: E9 38
00CABB  1  8D 6E 05         sta $056E                   ; $CABB: 8D 6E 05
00CABE  1               
00CABE  1  CD 6C 05         cmp $056C                   ; $CABE: CD 6C 05
00CAC1  1  B0 04            bcs FinishTrajectorySequence     ; $CAC1: B0 04
00CAC3  1               
00CAC3  1  C9 50            cmp #$50                    ; $CAC3: C9 50
00CAC5  1  90 E9            bcc WaitForTrajectoryLimit
00CAC7  1                                               ; $CAC5: 90 E9
00CAC7  1               
00CAC7  1               ; ----------------------------------------------------------------------------
00CAC7  1               ; Reset position structures and leave through the common engine exit.
00CAC7  1               ; A is zero after ClearBaseAccelerationFields, so $5C is cleared.
00CAC7  1               ; ----------------------------------------------------------------------------
00CAC7  1               
00CAC7  1               FinishTrajectorySequence:            ; $CAC7
00CAC7  1  20 4F C9         jsr ClearBasePositionFields            ; $CAC7: 20 4F C9
00CACA  1  20 43 C9         jsr ClearBaseAccelerationFields            ; $CACA: 20 43 C9
00CACD  1               
00CACD  1  85 5C            sta BaseMotionActive            ; $CACD: 85 5C
00CACF  1               
00CACF  1  4C 6A EB         jmp CommonEngineExit                   ; $CACF: 4C 6A EB
00CAD2  1               
00CAD2  1               ; ============================================================================
00CAD2  1               ; $CAD2-$CB34
00CAD2  1               ; Evaluate object state and select a transition based on position-derived data.
00CAD2  1               ;
00CAD2  1               ; The routine uses the current base-object coordinates to calculate an index
00CAD2  1               ; into the four-byte table at $CB35. The selected signed table value is saved
00CAD2  1               ; in $5F and controls subsequent state transitions.
00CAD2  1               ; ============================================================================
00CAD2  1               
00CAD2  1               ; ----------------------------------------------------------------------------
00CAD2  1               ; Contract:
00CAD2  1               ;   Description: Implements Evaluate Trajectory Result.
00CAD2  1               ;   Entry: Registers: A, X, Y; Memory: trajectoryevaluationenabled, trajectoryresult, basemotioneventcount, $0509, $050a, $053a, $053b
00CAD2  1               ;   Returns/products: Registers/clobbers: A, X, Y
00CAD2  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00CAD2  1               ;   Memory effects: trajectoryresult, stateselector, $0598
00CAD2  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00CAD2  1               ;          comparison, load, or store path and are not a stable API product.
00CAD2  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 2.
00CAD2  1               ; ----------------------------------------------------------------------------
00CAD2  1               EvaluateTrajectoryResult:                   ; $CAD2
00CAD2  1  A5 86            lda TrajectoryEvaluationEnabled                 ; $CAD2: A5 86
00CAD4  1  10 5E            bpl TrajectoryResultReturn     ; $CAD4: 10 5E
00CAD6  1               
00CAD6  1  A5 5F            lda TrajectoryResult            ; $CAD6: A5 5F
00CAD8  1  05 5E            ora BaseMotionEventCount        ; $CAD8: 05 5E
00CADA  1  D0 58            bne TrajectoryResultReturn     ; $CADA: D0 58
00CADC  1               
00CADC  1               ; ----------------------------------------------------------------------------
00CADC  1               ; Normalize the base horizontal position.
00CADC  1               ;
00CADC  1               ; Input:
00CADC  1               ;   Y = $0509
00CADC  1               ;   A = $050A
00CADC  1               ;
00CADC  1               ; The helper at $E7CB processes the 16-bit value in A:Y.
00CADC  1               ; ----------------------------------------------------------------------------
00CADC  1               
00CADC  1  AC 09 05         ldy $0509                   ; $CADC: AC 09 05
00CADF  1  AD 0A 05         lda $050A                   ; $CADF: AD 0A 05
00CAE2  1               
00CAE2  1  20 CB E7         jsr AbsoluteValueAY                   ; $CAE2: 20 CB E7
00CAE5  1               
00CAE5  1               ; ----------------------------------------------------------------------------
00CAE5  1               ; Subtract eight from the normalized high/result byte and preserve it.
00CAE5  1               ; ----------------------------------------------------------------------------
00CAE5  1               
00CAE5  1  38               sec                         ; $CAE5: 38
00CAE6  1  E9 08            sbc #$08                    ; $CAE6: E9 08
00CAE8  1               
00CAE8  1  48               pha                         ; $CAE8: 48
00CAE9  1               
00CAE9  1               ; ----------------------------------------------------------------------------
00CAE9  1               ; Compare the normalized low result in Y against $053A, then subtract $053B.
00CAE9  1               ;
00CAE9  1               ; ASL followed by LDA #$00 / ROL converts the comparison result in carry into
00CAE9  1               ; a zero-or-one high component, which becomes an index contribution.
00CAE9  1               ; ----------------------------------------------------------------------------
00CAE9  1               
00CAE9  1  CC 3A 05         cpy $053A                   ; $CAE9: CC 3A 05
00CAEC  1  ED 3B 05         sbc $053B                   ; $CAEC: ED 3B 05
00CAEF  1               
00CAEF  1  0A               asl                         ; $CAEF: 0A
00CAF0  1               
00CAF0  1  A9 00            lda #$00                    ; $CAF0: A9 00
00CAF2  1  2A               rol                         ; $CAF2: 2A
00CAF3  1  AA               tax                         ; $CAF3: AA
00CAF4  1               
00CAF4  1               ; ----------------------------------------------------------------------------
00CAF4  1               ; Add the normalized position to $053A/$053B.
00CAF4  1               ; ----------------------------------------------------------------------------
00CAF4  1               
00CAF4  1  98               tya                         ; $CAF4: 98
00CAF5  1  6D 3A 05         adc $053A                   ; $CAF5: 6D 3A 05
00CAF8  1               
00CAF8  1  68               pla                         ; $CAF8: 68
00CAF9  1  6D 3B 05         adc $053B                   ; $CAF9: 6D 3B 05
00CAFC  1               
00CAFC  1               ; ----------------------------------------------------------------------------
00CAFC  1               ; Convert the result and carry state into a table index.
00CAFC  1               ;
00CAFC  1               ; X receives a value in the range $00-$03.
00CAFC  1               ; ----------------------------------------------------------------------------
00CAFC  1               
00CAFC  1  0A               asl                         ; $CAFC: 0A
00CAFD  1               
00CAFD  1  8A               txa                         ; $CAFD: 8A
00CAFE  1  2A               rol                         ; $CAFE: 2A
00CAFF  1  AA               tax                         ; $CAFF: AA
00CB00  1               
00CB00  1  BD 35 CB         lda TrajectoryResultTable,x            ; $CB00: BD 35 CB
00CB03  1  85 5F            sta TrajectoryResult            ; $CB03: 85 5F
00CB05  1               
00CB05  1  10 2D            bpl TrajectoryResultReturn     ; $CB05: 10 2D
00CB07  1               
00CB07  1               ; ----------------------------------------------------------------------------
00CB07  1               ; Handle the negative table-result path.
00CB07  1               ; ----------------------------------------------------------------------------
00CB07  1               
00CB07  1  A5 88            lda MotionDirectionState                 ; $CB07: A5 88
00CB09  1  D0 13            bne ApplyNegativeTrajectoryResult
00CB0B  1                                               ; $CB09: D0 13
00CB0B  1               
00CB0B  1  A9 02            lda #$02                    ; $CB0B: A9 02
00CB0D  1  C5 62            cmp PrimarySequenceState                 ; $CB0D: C5 62
00CB0F  1  D0 0D            bne ApplyNegativeTrajectoryResult
00CB11  1                                               ; $CB0F: D0 0D
00CB11  1               
00CB11  1  0A               asl                         ; $CB11: 0A
00CB12  1                                               ; A = $04
00CB12  1               
00CB12  1  85 72            sta StateSelector           ; $CB12: 85 72
00CB14  1               
00CB14  1  A9 FF            lda #$FF                    ; $CB14: A9 FF
00CB16  1  8D 98 05         sta $0598                   ; $CB16: 8D 98 05
00CB19  1               
00CB19  1  E6 46            inc StateSequenceActive             ; $CB19: E6 46
00CB1B  1               
00CB1B  1  4C E4 CC         jmp AdvanceAlternateStateSequence
00CB1E  1                                               ; $CB1B: 4C E4 CC
00CB1E  1               
00CB1E  1               ; ----------------------------------------------------------------------------
00CB1E  1               ; Update state variables and select one of two inline command records based on
00CB1E  1               ; the sign of $050A.
00CB1E  1               ; ----------------------------------------------------------------------------
00CB1E  1               
00CB1E  1               ApplyNegativeTrajectoryResult:       ; $CB1E
00CB1E  1  E6 60            inc PendingStateTransition                 ; $CB1E: E6 60
00CB20  1  C6 46            dec StateSequenceActive             ; $CB20: C6 46
00CB22  1               
00CB22  1  AD 0A 05         lda $050A                   ; $CB22: AD 0A 05
00CB25  1  30 07            bmi QueueNegativeResultCommand   ; $CB25: 30 07
00CB27  1               
00CB27  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $CB27: 20 0A EB
00CB2A  1               
00CB2A  1                   ; Inline command record consumed by QueueInlineObjectEvent.
00CB2A  1  18 4C CC         .byte $18,$4C,$CC           ; $CB2A-$CB2C
00CB2D  1               
00CB2D  1  60               rts                         ; $CB2D: 60
00CB2E  1               
00CB2E  1               QueueNegativeResultCommand:          ; $CB2E
00CB2E  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $CB2E: 20 0A EB
00CB31  1               
00CB31  1                   ; Alternate inline command record consumed by QueueInlineObjectEvent.
00CB31  1  1C 4C CC         .byte $1C,$4C,$CC           ; $CB31-$CB33
00CB34  1               
00CB34  1               TrajectoryResultReturn:            ; $CB34
00CB34  1  60               rts                         ; $CB34: 60
00CB35  1               
00CB35  1               ; ============================================================================
00CB35  1               ; $CB35-$CB38
00CB35  1               ; Signed state-result lookup table.
00CB35  1               ;
00CB35  1               ; Indexed by the two-bit value calculated at $CAFC-$CAFF.
00CB35  1               ; ============================================================================
00CB35  1               
00CB35  1               TrajectoryResultTable:                     ; $CB35
00CB35  1  FF FF 01 00      .byte $FF,$FF,$01,$00
00CB39  1               
00CB39  1               ; ============================================================================
00CB39  1               ; $CB39-$CB7C
00CB39  1               ; Save base coordinates, prepare three object records, and repeatedly update
00CB39  1               ; them until the first updated record produces a negative high byte.
00CB39  1               ; ============================================================================
00CB39  1               
00CB39  1               SimulateObjectTrajectories:                   ; $CB39
00CB39  1  AD 02 05         lda $0502                   ; $CB39: AD 02 05
00CB3C  1  85 53            sta SavedBaseXLo            ; $CB3C: 85 53
00CB3E  1               
00CB3E  1  AD 03 05         lda $0503                   ; $CB3E: AD 03 05
00CB41  1  85 54            sta SavedBaseXHi            ; $CB41: 85 54
00CB43  1               
00CB43  1  AD 33 05         lda $0533                   ; $CB43: AD 33 05
00CB46  1  85 55            sta SavedBaseYLo            ; $CB46: 85 55
00CB48  1               
00CB48  1  AD 34 05         lda $0534                   ; $CB48: AD 34 05
00CB4B  1  85 56            sta SavedBaseYHi            ; $CB4B: 85 56
00CB4D  1               
00CB4D  1  20 4C EB         jsr SelectObjectEventBank0                   ; $CB4D: 20 4C EB
00CB50  1               
00CB50  1               ; ----------------------------------------------------------------------------
00CB50  1               ; Prepare three object records.
00CB50  1               ;
00CB50  1               ; The records begin at offsets:
00CB50  1               ;
00CB50  1               ;   X = $00
00CB50  1               ;   X = $31
00CB50  1               ;   X = $62
00CB50  1               ; ----------------------------------------------------------------------------
00CB50  1               
00CB50  1  A2 00            ldx #$00                    ; $CB50: A2 00
00CB52  1  20 7D CB         jsr PrepareFixedPointObject
00CB55  1                                               ; $CB52: 20 7D CB
00CB55  1               
00CB55  1  A2 31            ldx #$31                    ; $CB55: A2 31
00CB57  1  20 7D CB         jsr PrepareFixedPointObject
00CB5A  1                                               ; $CB57: 20 7D CB
00CB5A  1               
00CB5A  1  A2 62            ldx #$62                    ; $CB5A: A2 62
00CB5C  1  20 7D CB         jsr PrepareFixedPointObject
00CB5F  1                                               ; $CB5C: 20 7D CB
00CB5F  1               
00CB5F  1               ; ----------------------------------------------------------------------------
00CB5F  1               ; Initialize an update counter and enter the frame/update loop.
00CB5F  1               ; ----------------------------------------------------------------------------
00CB5F  1               
00CB5F  1  A2 20            ldx #$20                    ; $CB5F: A2 20
00CB61  1  86 61            stx UpdateCounter           ; $CB61: 86 61
00CB63  1               
00CB63  1               Routine_CB63_UpdateLoop:        ; $CB63
00CB63  1  20 4C EB         jsr SelectObjectEventBank0                   ; $CB63: 20 4C EB
00CB66  1               
00CB66  1               ; ----------------------------------------------------------------------------
00CB66  1               ; Update the third record first.
00CB66  1               ;
00CB66  1               ; If its resulting high byte is negative, restart the entire routine.
00CB66  1               ; ----------------------------------------------------------------------------
00CB66  1               
00CB66  1  A2 62            ldx #$62                    ; $CB66: A2 62
00CB68  1  20 C4 CB         jsr IntegrateFixedPointObject
00CB6B  1                                               ; $CB68: 20 C4 CB
00CB6B  1               
00CB6B  1  30 CC            bmi SimulateObjectTrajectories            ; $CB6B: 30 CC
00CB6D  1               
00CB6D  1               ; ----------------------------------------------------------------------------
00CB6D  1               ; Update the remaining two records.
00CB6D  1               ; ----------------------------------------------------------------------------
00CB6D  1               
00CB6D  1  A2 31            ldx #$31                    ; $CB6D: A2 31
00CB6F  1  20 C4 CB         jsr IntegrateFixedPointObject
00CB72  1                                               ; $CB6F: 20 C4 CB
00CB72  1               
00CB72  1  A2 00            ldx #$00                    ; $CB72: A2 00
00CB74  1  20 C4 CB         jsr IntegrateFixedPointObject
00CB77  1                                               ; $CB74: 20 C4 CB
00CB77  1               
00CB77  1               ; ----------------------------------------------------------------------------
00CB77  1               ; Continue for $20 update cycles, then restart the routine.
00CB77  1               ; ----------------------------------------------------------------------------
00CB77  1               
00CB77  1  C6 61            dec UpdateCounter           ; $CB77: C6 61
00CB79  1  D0 E8            bne Routine_CB63_UpdateLoop ; $CB79: D0 E8
00CB7B  1               
00CB7B  1  F0 BC            beq SimulateObjectTrajectories            ; $CB7B: F0 BC
00CB7D  1                                               ; Always taken because $61 is zero.
00CB7D  1               
00CB7D  1               ; ============================================================================
00CB7D  1               ; $CB7D-$CBC3
00CB7D  1               ; Prepare one fixed-point object record.
00CB7D  1               ;
00CB7D  1               ; Entry:
00CB7D  1               ;   X = object-record offset
00CB7D  1               ;
00CB7D  1               ; Input fields:
00CB7D  1               ;   $0506,X
00CB7D  1               ;   $0507,X/$0508,X
00CB7D  1               ;   $0509,X/$050A,X
00CB7D  1               ;
00CB7D  1               ; Output fields:
00CB7D  1               ;   $0500,X/$0501,X
00CB7D  1               ;   $0502,X/$0503,X
00CB7D  1               ;   $0504,X/$0505,X
00CB7D  1               ; ============================================================================
00CB7D  1               
00CB7D  1               PrepareFixedPointObject:     ; $CB7D
00CB7D  1  A0 00            ldy #$00                    ; $CB7D: A0 00
00CB7F  1               
00CB7F  1               ; ----------------------------------------------------------------------------
00CB7F  1               ; Sign-extend $0506,X, multiply it by four, and store the result in
00CB7F  1               ; $0500,X/$0501,X.
00CB7F  1               ; ----------------------------------------------------------------------------
00CB7F  1               
00CB7F  1  BD 06 05         lda $0506,x                 ; $CB7F: BD 06 05
00CB82  1  48               pha                         ; $CB82: 48
00CB83  1               
00CB83  1  10 01            bpl Routine_CB86_FirstPositive
00CB85  1                                               ; $CB83: 10 01
00CB85  1               
00CB85  1  88               dey                         ; $CB85: 88
00CB86  1                                               ; Y = $FF for a negative input.
00CB86  1               
00CB86  1               Routine_CB86_FirstPositive:     ; $CB86
00CB86  1  98               tya                         ; $CB86: 98
00CB87  1  9D 01 05         sta $0501,x                 ; $CB87: 9D 01 05
00CB8A  1               
00CB8A  1  68               pla                         ; $CB8A: 68
00CB8B  1               
00CB8B  1  0A               asl                         ; $CB8B: 0A
00CB8C  1  3E 01 05         rol $0501,x                 ; $CB8C: 3E 01 05
00CB8F  1               
00CB8F  1  0A               asl                         ; $CB8F: 0A
00CB90  1  3E 01 05         rol $0501,x                 ; $CB90: 3E 01 05
00CB93  1               
00CB93  1  9D 00 05         sta $0500,x                 ; $CB93: 9D 00 05
00CB96  1               
00CB96  1               ; ----------------------------------------------------------------------------
00CB96  1               ; Sign-extend and scale $0507,X/$0508,X.
00CB96  1               ;
00CB96  1               ; The low byte is initially shifted into $05. The high byte and temporary
00CB96  1               ; value are then rotated to form the output at $0504,X/$0505,X.
00CB96  1               ; ----------------------------------------------------------------------------
00CB96  1               
00CB96  1  A0 00            ldy #$00                    ; $CB96: A0 00
00CB98  1               
00CB98  1  BD 07 05         lda $0507,x                 ; $CB98: BD 07 05
00CB9B  1  0A               asl                         ; $CB9B: 0A
00CB9C  1  85 05            sta MathTemp05              ; $CB9C: 85 05
00CB9E  1               
00CB9E  1  BD 08 05         lda $0508,x                 ; $CB9E: BD 08 05
00CBA1  1  48               pha                         ; $CBA1: 48
00CBA2  1               
00CBA2  1  10 01            bpl Routine_CBA5_SecondPositive
00CBA4  1                                               ; $CBA2: 10 01
00CBA4  1               
00CBA4  1  88               dey                         ; $CBA4: 88
00CBA5  1                                               ; Y = $FF for a negative input.
00CBA5  1               
00CBA5  1               Routine_CBA5_SecondPositive:    ; $CBA5
00CBA5  1  98               tya                         ; $CBA5: 98
00CBA6  1  9D 05 05         sta $0505,x                 ; $CBA6: 9D 05 05
00CBA9  1               
00CBA9  1  68               pla                         ; $CBA9: 68
00CBAA  1               
00CBAA  1  2A               rol                         ; $CBAA: 2A
00CBAB  1  3E 05 05         rol $0505,x                 ; $CBAB: 3E 05 05
00CBAE  1               
00CBAE  1  06 05            asl MathTemp05              ; $CBAE: 06 05
00CBB0  1               
00CBB0  1  2A               rol                         ; $CBB0: 2A
00CBB1  1  3E 05 05         rol $0505,x                 ; $CBB1: 3E 05 05
00CBB4  1               
00CBB4  1  9D 04 05         sta $0504,x                 ; $CBB4: 9D 04 05
00CBB7  1               
00CBB7  1               ; ----------------------------------------------------------------------------
00CBB7  1               ; Copy the source position into the working position.
00CBB7  1               ; ----------------------------------------------------------------------------
00CBB7  1               
00CBB7  1  BD 09 05         lda $0509,x                 ; $CBB7: BD 09 05
00CBBA  1  9D 02 05         sta $0502,x                 ; $CBBA: 9D 02 05
00CBBD  1               
00CBBD  1  BD 0A 05         lda $050A,x                 ; $CBBD: BD 0A 05
00CBC0  1  9D 03 05         sta $0503,x                 ; $CBC0: 9D 03 05
00CBC3  1               
00CBC3  1  60               rts                         ; $CBC3: 60
00CBC4  1               
00CBC4  1               ; ============================================================================
00CBC4  1               ; $CBC4-$CBE9
00CBC4  1               ; Update one fixed-point object record.
00CBC4  1               ;
00CBC4  1               ; Entry:
00CBC4  1               ;   X = object-record offset
00CBC4  1               ;
00CBC4  1               ; Operation:
00CBC4  1               ;   velocity += acceleration
00CBC4  1               ;   position += velocity
00CBC4  1               ;
00CBC4  1               ; The final A value is the updated position high byte, so callers can test its
00CBC4  1               ; sign immediately after return.
00CBC4  1               ; ============================================================================
00CBC4  1               
00CBC4  1               IntegrateFixedPointObject:      ; $CBC4
00CBC4  1  18               clc                         ; $CBC4: 18
00CBC5  1               
00CBC5  1               ; ----------------------------------------------------------------------------
00CBC5  1               ; Add acceleration $0500/$0501 to velocity $0504/$0505.
00CBC5  1               ; ----------------------------------------------------------------------------
00CBC5  1               
00CBC5  1  BD 00 05         lda $0500,x                 ; $CBC5: BD 00 05
00CBC8  1  7D 04 05         adc $0504,x                 ; $CBC8: 7D 04 05
00CBCB  1  9D 04 05         sta $0504,x                 ; $CBCB: 9D 04 05
00CBCE  1               
00CBCE  1  BD 01 05         lda $0501,x                 ; $CBCE: BD 01 05
00CBD1  1  7D 05 05         adc $0505,x                 ; $CBD1: 7D 05 05
00CBD4  1  9D 05 05         sta $0505,x                 ; $CBD4: 9D 05 05
00CBD7  1               
00CBD7  1  A8               tay                         ; $CBD7: A8
00CBD8  1                                               ; Preserve the updated velocity high byte.
00CBD8  1               
00CBD8  1               ; ----------------------------------------------------------------------------
00CBD8  1               ; Add velocity $0504/$0505 to position $0502/$0503.
00CBD8  1               ; ----------------------------------------------------------------------------
00CBD8  1               
00CBD8  1  18               clc                         ; $CBD8: 18
00CBD9  1               
00CBD9  1  BD 04 05         lda $0504,x                 ; $CBD9: BD 04 05
00CBDC  1  7D 02 05         adc $0502,x                 ; $CBDC: 7D 02 05
00CBDF  1  9D 02 05         sta $0502,x                 ; $CBDF: 9D 02 05
00CBE2  1               
00CBE2  1  98               tya                         ; $CBE2: 98
00CBE3  1               
00CBE3  1  7D 03 05         adc $0503,x                 ; $CBE3: 7D 03 05
00CBE6  1  9D 03 05         sta $0503,x                 ; $CBE6: 9D 03 05
00CBE9  1               
00CBE9  1  60               rts                         ; $CBE9: 60
00CBEA  1               
00CBEA  1               ; ============================================================================
00CBEA  1               ; $CBEA-$CC00
00CBEA  1               ; Geometry/collision test helper
00CBEA  1               ;
00CBEA  1               ; Entry points:
00CBEA  1               ;   $CBEA loads X from $E1.
00CBEA  1               ;   $CBEC uses the X value supplied by the caller.
00CBEA  1               ; ============================================================================
00CBEA  1               
00CBEA  1               ; ----------------------------------------------------------------------------
00CBEA  1               ; Contract:
00CBEA  1               ;   Description: Implements Test Current Object Collision.
00CBEA  1               ;   Entry: Registers: A; Memory: $e1
00CBEA  1               ;   Returns/products: Registers/clobbers: A, X
00CBEA  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00CBEA  1               ;   Memory effects: $b2, $b3, $b4, $b5
00CBEA  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00CBEA  1               ;          comparison, load, or store path and are not a stable API product.
00CBEA  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 2.
00CBEA  1               ; ----------------------------------------------------------------------------
00CBEA  1               TestCurrentObjectCollision:                   ; $CBEA
00CBEA  1  A6 E1            ldx CurrentObjectIndex                     ; $CBEA: A6 E1
00CBEC  1               
00CBEC  1               ; ----------------------------------------------------------------------------
00CBEC  1               ; Contract:
00CBEC  1               ;   Description: Implements Test Object Collision.
00CBEC  1               ;   Entry: Registers: A
00CBEC  1               ;   Returns/products: Registers/clobbers: A
00CBEC  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00CBEC  1               ;   Memory effects: $b2, $b3, $b4, $b5
00CBEC  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00CBEC  1               ;          comparison, load, or store path and are not a stable API product.
00CBEC  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 2.
00CBEC  1               ; ----------------------------------------------------------------------------
00CBEC  1               TestObjectCollision:                   ; $CBEC
00CBEC  1  A9 00            lda #$00                    ; $CBEC: A9 00
00CBEE  1               
00CBEE  1  85 B2            sta $B2                     ; $CBEE: 85 B2
00CBF0  1  85 B3            sta $B3                     ; $CBF0: 85 B3
00CBF2  1  85 B4            sta $B4                     ; $CBF2: 85 B4
00CBF4  1               
00CBF4  1  A9 07            lda #$07                    ; $CBF4: A9 07
00CBF6  1  85 B5            sta $B5                     ; $CBF6: 85 B5
00CBF8  1               
00CBF8  1  20 DD E4         jsr CalculateGeometryDifference                   ; $CBF8: 20 DD E4
00CBFB  1  20 02 E5         jsr EvaluateGeometryDifference                   ; $CBFB: 20 02 E5
00CBFE  1               
00CBFE  1  C9 42            cmp #$42                    ; $CBFE: C9 42
00CC00  1  60               rts                         ; $CC00: 60
00CC01  1               
00CC01  1               ; ============================================================================
00CC01  1               ; $CC01-$CC3B
00CC01  1               ; Advance state $63, update display/event slots, and initialize the next
00CC01  1               ; state-dependent object or animation.
00CC01  1               ; ============================================================================
00CC01  1               
00CC01  1               ; ----------------------------------------------------------------------------
00CC01  1               ; Contract:
00CC01  1               ;   Description: Implements Advance Primary State Sequence.
00CC01  1               ;   Entry: Registers: A; Memory: transitionsequencestate, $0596
00CC01  1               ;   Returns/products: Registers/clobbers: A, Y; Flags: condition flags may carry result state
00CC01  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00CC01  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00CC01  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00CC01  1               ;          comparison, load, or store path and are not a stable API product.
00CC01  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00CC01  1               ; ----------------------------------------------------------------------------
00CC01  1               AdvancePrimaryStateSequence:                   ; $CC01
00CC01  1  E6 63            inc TransitionSequenceState                 ; $CC01: E6 63
00CC03  1               
00CC03  1  A5 63            lda TransitionSequenceState                 ; $CC03: A5 63
00CC05  1  C9 04            cmp #$04                    ; $CC05: C9 04
00CC07  1  90 17            bcc HandleEarlyPrimaryState
00CC09  1                                               ; $CC07: 90 17
00CC09  1               
00CC09  1               ; ----------------------------------------------------------------------------
00CC09  1               ; State $63 is four or greater.
00CC09  1               ;
00CC09  1               ; Process event slots $0F and $0D, execute an inline command, then call the
00CC09  1               ; helper at $CF4A. A delay/count value of $1E is selected.
00CC09  1               ; ----------------------------------------------------------------------------
00CC09  1               
00CC09  1  A0 0F            ldy #$0F                    ; $CC09: A0 0F
00CC0B  1  20 66 EB         jsr DispatchNextQueuedEvent                   ; $CC0B: 20 66 EB
00CC0E  1               
00CC0E  1  A0 0D            ldy #$0D                    ; $CC0E: A0 0D
00CC10  1  20 66 EB         jsr DispatchNextQueuedEvent                   ; $CC10: 20 66 EB
00CC13  1               
00CC13  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $CC13: 20 0A EB
00CC16  1               
00CC16  1                   ; Inline command record consumed by QueueInlineObjectEvent.
00CC16  1  06 ED D9         .byte $06,$ED,$D9           ; $CC16-$CC18
00CC19  1               
00CC19  1  20 4A CF         jsr ClearPrimaryStateField                   ; $CC19: 20 4A CF
00CC1C  1               
00CC1C  1  A9 1E            lda #$1E                    ; $CC1C: A9 1E
00CC1E  1  D0 0A            bne QueuePrimaryStateEvent   ; $CC1E: D0 0A
00CC20  1                                               ; Always taken because A is nonzero.
00CC20  1               
00CC20  1               ; ----------------------------------------------------------------------------
00CC20  1               ; State $63 is below four.
00CC20  1               ;
00CC20  1               ; Pass A = $63 + 2 to $CF2F, then select a value of $18.
00CC20  1               ; ----------------------------------------------------------------------------
00CC20  1               
00CC20  1               HandleEarlyPrimaryState:       ; $CC20
00CC20  1  18               clc                         ; $CC20: 18
00CC21  1               
00CC21  1  A5 63            lda TransitionSequenceState                 ; $CC21: A5 63
00CC23  1  69 02            adc #$02                    ; $CC23: 69 02
00CC25  1               
00CC25  1  20 2F CF         jsr BuildStateMarkerEntries                   ; $CC25: 20 2F CF
00CC28  1               
00CC28  1  A9 18            lda #$18                    ; $CC28: A9 18
00CC2A  1               
00CC2A  1               ; ----------------------------------------------------------------------------
00CC2A  1               ; Pass the selected value, either $18 or $1E, to $CF11.
00CC2A  1               ; ----------------------------------------------------------------------------
00CC2A  1               
00CC2A  1               QueuePrimaryStateEvent:          ; $CC2A
00CC2A  1  20 11 CF         jsr AddTimedStateEvent                   ; $CC2A: 20 11 CF
00CC2D  1               
00CC2D  1               ; ----------------------------------------------------------------------------
00CC2D  1               ; Perform a one-time inline command when $0596 is zero.
00CC2D  1               ; ----------------------------------------------------------------------------
00CC2D  1               
00CC2D  1  AD 96 05         lda $0596                   ; $CC2D: AD 96 05
00CC30  1  D0 09            bne Routine_CC3B_Return     ; $CC30: D0 09
00CC32  1               
00CC32  1  EE 96 05         inc $0596                   ; $CC32: EE 96 05
00CC35  1               
00CC35  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $CC35: 20 0A EB
00CC38  1               
00CC38  1                   ; Inline command record consumed by QueueInlineObjectEvent.
00CC38  1  28 3B CC         .byte $28,$3B,$CC           ; $CC38-$CC3A
00CC3B  1               
00CC3B  1               Routine_CC3B_Return:            ; $CC3B
00CC3B  1  60               rts                         ; $CC3B: 60
00CC3C  1               
00CC3C  1               ; ============================================================================
00CC3C  1               ; $CC3C-$CC4C
00CC3C  1               ; Timed state transition.
00CC3C  1               ;
00CC3C  1               ; Increment $03B1, wait for $3C ticks, restore $03B1, clear the one-time flag,
00CC3C  1               ; and leave through the common engine exit.
00CC3C  1               ; ============================================================================
00CC3C  1               
00CC3C  1               RunPrimaryStateDelay:                   ; $CC3C
00CC3C  1  EE B1 03         inc $03B1                   ; $CC3C: EE B1 03
00CC3F  1               
00CC3F  1  A9 3C            lda #$3C                    ; $CC3F: A9 3C
00CC41  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $CC41: 20 41 EB
00CC44  1               
00CC44  1  CE B1 03         dec $03B1                   ; $CC44: CE B1 03
00CC47  1  CE 96 05         dec $0596                   ; $CC47: CE 96 05
00CC4A  1               
00CC4A  1  4C 6A EB         jmp CommonEngineExit                   ; $CC4A: 4C 6A EB
00CC4D  1               
00CC4D  1               ; ============================================================================
00CC4D  1               ; $CC4D-$CC79
00CC4D  1               ; Advance state $62, update an indexed animation value, wait, restore it,
00CC4D  1               ; and leave through the common engine exit.
00CC4D  1               ; ============================================================================
00CC4D  1               
00CC4D  1               AdvanceSecondaryStateSequence:                   ; $CC4D
00CC4D  1  A5 62            lda PrimarySequenceState                 ; $CC4D: A5 62
00CC4F  1  C9 02            cmp #$02                    ; $CC4F: C9 02
00CC51  1  B0 05            bcs QueueSecondaryStateEvent   ; $CC51: B0 05
00CC53  1               
00CC53  1               ; ----------------------------------------------------------------------------
00CC53  1               ; Advance $62 while it is below two and run the associated setup helper.
00CC53  1               ; ----------------------------------------------------------------------------
00CC53  1               
00CC53  1  E6 62            inc PrimarySequenceState                 ; $CC53: E6 62
00CC55  1  20 23 CF         jsr QueuePrimaryStateMarker                   ; $CC55: 20 23 CF
00CC58  1               
00CC58  1               ; ----------------------------------------------------------------------------
00CC58  1               ; Pass state value $06 to the helper at $CF11.
00CC58  1               ; ----------------------------------------------------------------------------
00CC58  1               
00CC58  1               QueueSecondaryStateEvent:          ; $CC58
00CC58  1  A9 06            lda #$06                    ; $CC58: A9 06
00CC5A  1  20 11 CF         jsr AddTimedStateEvent                   ; $CC5A: 20 11 CF
00CC5D  1               
00CC5D  1               ; ----------------------------------------------------------------------------
00CC5D  1               ; Convert the current object index in $E1 to the corresponding animation-table
00CC5D  1               ; index, then increment $039A,X.
00CC5D  1               ; ----------------------------------------------------------------------------
00CC5D  1               
00CC5D  1  A6 E1            ldx CurrentObjectIndex      ; $CC5D: A6 E1
00CC5F  1  20 38 E7         jsr ConvertObjectOffsetToDisplayIndex                   ; $CC5F: 20 38 E7
00CC62  1               
00CC62  1  FE 9A 03         inc $039A,x                 ; $CC62: FE 9A 03
00CC65  1               
00CC65  1               ; ----------------------------------------------------------------------------
00CC65  1               ; Wait for $5A ticks.
00CC65  1               ; ----------------------------------------------------------------------------
00CC65  1               
00CC65  1  A9 5A            lda #$5A                    ; $CC65: A9 5A
00CC67  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $CC67: 20 41 EB
00CC6A  1               
00CC6A  1               ; ----------------------------------------------------------------------------
00CC6A  1               ; Recalculate the animation-table index and restore $039A,X.
00CC6A  1               ; ----------------------------------------------------------------------------
00CC6A  1               
00CC6A  1  A6 E1            ldx CurrentObjectIndex      ; $CC6A: A6 E1
00CC6C  1  20 38 E7         jsr ConvertObjectOffsetToDisplayIndex                   ; $CC6C: 20 38 E7
00CC6F  1               
00CC6F  1  DE 9A 03         dec $039A,x                 ; $CC6F: DE 9A 03
00CC72  1               
00CC72  1               ; ----------------------------------------------------------------------------
00CC72  1               ; Process command $08 and leave through the common engine exit.
00CC72  1               ; ----------------------------------------------------------------------------
00CC72  1               
00CC72  1  A2 08            ldx #$08                    ; $CC72: A2 08
00CC74  1  20 2A EB         jsr ProcessQueuedObjectEvent                   ; $CC74: 20 2A EB
00CC77  1               
00CC77  1  4C 6A EB         jmp CommonEngineExit                   ; $CC77: 4C 6A EB
00CC7A  1               
00CC7A  1               ; ============================================================================
00CC7A  1               ; $CC7A-$CCB8
00CC7A  1               ; Advance states PrimarySequenceState and $64, run state-specific setup, and dispatch a
00CC7A  1               ; one-time inline command.
00CC7A  1               ; ============================================================================
00CC7A  1               
00CC7A  1               AdvanceDualStateSequence:                   ; $CC7A
00CC7A  1  A9 0C            lda #$0C                    ; $CC7A: A9 0C
00CC7C  1  20 11 CF         jsr AddTimedStateEvent                   ; $CC7C: 20 11 CF
00CC7F  1               
00CC7F  1  E6 62            inc PrimarySequenceState                 ; $CC7F: E6 62
00CC81  1  20 23 CF         jsr QueuePrimaryStateMarker                   ; $CC81: 20 23 CF
00CC84  1               
00CC84  1  A5 62            lda PrimarySequenceState                 ; $CC84: A5 62
00CC86  1  C9 03            cmp #$03                    ; $CC86: C9 03
00CC88  1  90 20            bcc Routine_CCAA_OneTimeCommand
00CC8A  1                                               ; $CC88: 90 20
00CC8A  1               ; ----------------------------------------------------------------------------
00CC8A  1               ; PrimarySequenceState has reached three.
00CC8A  1               ; ----------------------------------------------------------------------------
00CC8A  1               
00CC8A  1  A9 12            lda #$12                    ; $CC8A: A9 12
00CC8C  1  20 11 CF         jsr AddTimedStateEvent                   ; $CC8C: 20 11 CF
00CC8F  1               
00CC8F  1  20 4A CF         jsr ClearPrimaryStateField                   ; $CC8F: 20 4A CF
00CC92  1               
00CC92  1  E6 64            inc SecondarySequenceState                 ; $CC92: E6 64
00CC94  1  20 2A CF         jsr QueueSecondaryStateMarker                   ; $CC94: 20 2A CF
00CC97  1               
00CC97  1  A5 64            lda SecondarySequenceState                 ; $CC97: A5 64
00CC99  1  C9 03            cmp #$03                    ; $CC99: C9 03
00CC9B  1  90 0D            bcc Routine_CCAA_OneTimeCommand
00CC9D  1                                               ; $CC9B: 90 0D
00CC9D  1               
00CC9D  1               ; ----------------------------------------------------------------------------
00CC9D  1               ; Both state counters have reached their thresholds.
00CC9D  1               ; ----------------------------------------------------------------------------
00CC9D  1               
00CC9D  1  A9 43            lda #$43                    ; $CC9D: A9 43
00CC9F  1  20 51 CF         jsr ClearStateFieldPair                   ; $CC9F: 20 51 CF
00CCA2  1               
00CCA2  1  A9 3C            lda #$3C                    ; $CCA2: A9 3C
00CCA4  1  20 11 CF         jsr AddTimedStateEvent                   ; $CCA4: 20 11 CF
00CCA7  1               
00CCA7  1  20 22 CE         jsr FinishStateProgression                   ; $CCA7: 20 22 CE
00CCAA  1               
00CCAA  1               ; ----------------------------------------------------------------------------
00CCAA  1               ; Execute this inline command once while $0596 is zero.
00CCAA  1               ; ----------------------------------------------------------------------------
00CCAA  1               
00CCAA  1               Routine_CCAA_OneTimeCommand:    ; $CCAA
00CCAA  1  AD 96 05         lda $0596                   ; $CCAA: AD 96 05
00CCAD  1  D0 09            bne Routine_CCB8_Return     ; $CCAD: D0 09
00CCAF  1               
00CCAF  1  EE 96 05         inc $0596                   ; $CCAF: EE 96 05
00CCB2  1               
00CCB2  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $CCB2: 20 0A EB
00CCB5  1               
00CCB5  1                   ; Inline command record consumed by QueueInlineObjectEvent.
00CCB5  1  28 B8 CC         .byte $28,$B8,$CC           ; $CCB5-$CCB7
00CCB8  1               
00CCB8  1               Routine_CCB8_Return:            ; $CCB8
00CCB8  1  60               rts                         ; $CCB8: 60
00CCB9  1               
00CCB9  1               ; ============================================================================
00CCB9  1               ; $CCB9-$CCE3
00CCB9  1               ; Timed animation/state sequence.
00CCB9  1               ;
00CCB9  1               ; $03B1 is decremented twice, incremented once, then decremented again with
00CCB9  1               ; delays between each change. It is finally set to $47.
00CCB9  1               ; ============================================================================
00CCB9  1               
00CCB9  1               RunDualStateAnimation:                   ; $CCB9
00CCB9  1  CE B1 03         dec $03B1                   ; $CCB9: CE B1 03
00CCBC  1               
00CCBC  1  A9 14            lda #$14                    ; $CCBC: A9 14
00CCBE  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $CCBE: 20 41 EB
00CCC1  1               
00CCC1  1  CE B1 03         dec $03B1                   ; $CCC1: CE B1 03
00CCC4  1               
00CCC4  1  A9 14            lda #$14                    ; $CCC4: A9 14
00CCC6  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $CCC6: 20 41 EB
00CCC9  1               
00CCC9  1               ; ----------------------------------------------------------------------------
00CCC9  1               ; Secondary entry point referenced by the inline command at $CCB5.
00CCC9  1               ; ----------------------------------------------------------------------------
00CCC9  1               
00CCC9  1               RunDualStateAnimationTail:                   ; $CCC9
00CCC9  1  EE B1 03         inc $03B1                   ; $CCC9: EE B1 03
00CCCC  1               
00CCCC  1  A9 14            lda #$14                    ; $CCCC: A9 14
00CCCE  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $CCCE: 20 41 EB
00CCD1  1               
00CCD1  1  CE B1 03         dec $03B1                   ; $CCD1: CE B1 03
00CCD4  1               
00CCD4  1  A9 3C            lda #$3C                    ; $CCD4: A9 3C
00CCD6  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $CCD6: 20 41 EB
00CCD9  1               
00CCD9  1  A9 47            lda #$47                    ; $CCD9: A9 47
00CCDB  1  8D B1 03         sta $03B1                   ; $CCDB: 8D B1 03
00CCDE  1               
00CCDE  1  CE 96 05         dec $0596                   ; $CCDE: CE 96 05
00CCE1  1               
00CCE1  1  4C 6A EB         jmp CommonEngineExit                   ; $CCE1: 4C 6A EB
00CCE4  1               
00CCE4  1               ; ============================================================================
00CCE4  1               ; $CCE4-$CD17
00CCE4  1               ; Alternate state transition entered from $CB1B.
00CCE4  1               ; ============================================================================
00CCE4  1               
00CCE4  1               AdvanceAlternateStateSequence:  ; $CCE4
00CCE4  1  E6 64            inc SecondarySequenceState                 ; $CCE4: E6 64
00CCE6  1               
00CCE6  1  20 2A CF         jsr QueueSecondaryStateMarker                   ; $CCE6: 20 2A CF
00CCE9  1               
00CCE9  1  A9 12            lda #$12                    ; $CCE9: A9 12
00CCEB  1  20 11 CF         jsr AddTimedStateEvent                   ; $CCEB: 20 11 CF
00CCEE  1               
00CCEE  1  A5 64            lda SecondarySequenceState                 ; $CCEE: A5 64
00CCF0  1  C9 03            cmp #$03                    ; $CCF0: C9 03
00CCF2  1  90 0E            bcc Routine_CD02_OptionalSetup
00CCF4  1                                               ; $CCF2: 90 0E
00CCF4  1               
00CCF4  1               ; ----------------------------------------------------------------------------
00CCF4  1               ; State $64 has reached three.
00CCF4  1               ; ----------------------------------------------------------------------------
00CCF4  1               
00CCF4  1  A9 3C            lda #$3C                    ; $CCF4: A9 3C
00CCF6  1  20 11 CF         jsr AddTimedStateEvent                   ; $CCF6: 20 11 CF
00CCF9  1               
00CCF9  1  20 22 CE         jsr FinishStateProgression                   ; $CCF9: 20 22 CE
00CCFC  1  20 45 CF         jsr ClearBothStateFields                   ; $CCFC: 20 45 CF
00CCFF  1               
00CCFF  1  4C 09 CD         jmp Routine_CD09_OneTimeCommand
00CD02  1                                               ; $CCFF: 4C 09 CD
00CD02  1               
00CD02  1               ; ----------------------------------------------------------------------------
00CD02  1               ; Run $CF4A only when $46 is nonzero.
00CD02  1               ; ----------------------------------------------------------------------------
00CD02  1               
00CD02  1               Routine_CD02_OptionalSetup:     ; $CD02
00CD02  1  A5 46            lda StateSequenceActive             ; $CD02: A5 46
00CD04  1  F0 03            beq Routine_CD09_OneTimeCommand
00CD06  1                                               ; $CD04: F0 03
00CD06  1               
00CD06  1  20 4A CF         jsr ClearPrimaryStateField                   ; $CD06: 20 4A CF
00CD09  1               
00CD09  1               ; ----------------------------------------------------------------------------
00CD09  1               ; Execute a second one-time inline command.
00CD09  1               ; ----------------------------------------------------------------------------
00CD09  1               
00CD09  1               Routine_CD09_OneTimeCommand:    ; $CD09
00CD09  1  AD 96 05         lda $0596                   ; $CD09: AD 96 05
00CD0C  1  D0 09            bne Routine_CD17_Return     ; $CD0C: D0 09
00CD0E  1               
00CD0E  1  EE 96 05         inc $0596                   ; $CD0E: EE 96 05
00CD11  1               
00CD11  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $CD11: 20 0A EB
00CD14  1               
00CD14  1                   ; Inline command record consumed by QueueInlineObjectEvent.
00CD14  1  28 17 CD         .byte $28,$17,$CD           ; $CD14-$CD16
00CD17  1               
00CD17  1               Routine_CD17_Return:            ; $CD17
00CD17  1  60               rts                         ; $CD17: 60
00CD18  1               
00CD18  1               ; ============================================================================
00CD18  1               ; $CD18-$CD21
00CD18  1               ; Select a state path using $72.
00CD18  1               ; ============================================================================
00CD18  1               
00CD18  1               DispatchStateSelectorAnimation:                   ; $CD18
00CD18  1  A6 72            ldx StateSelector           ; $CD18: A6 72
00CD1A  1               
00CD1A  1  E0 04            cpx #$04                    ; $CD1A: E0 04
00CD1C  1  F0 9B            beq RunDualStateAnimation            ; $CD1C: F0 9B
00CD1E  1                                               ; Branches backward to the timed sequence.
00CD1E  1               
00CD1E  1  A0 4A            ldy #$4A                    ; $CD1E: A0 4A
00CD20  1  D0 2F            bne StoreStateAnimationParameters   ; $CD20: D0 2F
00CD22  1                                               ; Always taken because Y is nonzero.
00CD22  1               
00CD22  1               ; ============================================================================
00CD22  1               ; $CD22-$CD2D
00CD22  1               ; Four parallel three-entry tables.
00CD22  1               ;
00CD22  1               ; X is expected to contain a value from $00-$02 when these tables are used by
00CD22  1               ; the routine beginning at $CD42.
00CD22  1               ; ============================================================================
00CD22  1               
00CD22  1               StateHorizontalLowTable:                     ; $CD22
00CD22  1  00 80 00         .byte $00,$80,$00
00CD25  1               
00CD25  1               StateHorizontalHighTable:                     ; $CD25
00CD25  1  09 FF F7         .byte $09,$FF,$F7
00CD28  1               
00CD28  1               StateVerticalLowTable:                     ; $CD28
00CD28  1  00 00 00         .byte $00,$00,$00
00CD2B  1               
00CD2B  1               StateVerticalHighTable:                     ; $CD2B
00CD2B  1  02 0A 02         .byte $02,$0A,$02
00CD2E  1               
00CD2E  1               ; ============================================================================
00CD2E  1               ; $CD2E-$CD41
00CD2E  1               ; Run state $42 and dispatch a one-time inline command.
00CD2E  1               ; ============================================================================
00CD2E  1               
00CD2E  1               ; ----------------------------------------------------------------------------
00CD2E  1               ; Contract:
00CD2E  1               ;   Description: Queues Selected State Marker.
00CD2E  1               ;   Entry: Memory: $0596
00CD2E  1               ;   Returns/products: Registers/clobbers: A
00CD2E  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00CD2E  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00CD2E  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00CD2E  1               ;          comparison, load, or store path and are not a stable API product.
00CD2E  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00CD2E  1               ; ----------------------------------------------------------------------------
00CD2E  1               QueueSelectedStateMarker:                   ; $CD2E
00CD2E  1  A9 42            lda #$42                    ; $CD2E: A9 42
00CD30  1  20 11 CF         jsr AddTimedStateEvent                   ; $CD30: 20 11 CF
00CD33  1               
00CD33  1  AD 96 05         lda $0596                   ; $CD33: AD 96 05
00CD36  1  D0 09            bne Routine_CD41_Return     ; $CD36: D0 09
00CD38  1               
00CD38  1  EE 96 05         inc $0596                   ; $CD38: EE 96 05
00CD3B  1               
00CD3B  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $CD3B: 20 0A EB
00CD3E  1               
00CD3E  1                   ; Inline command record consumed by QueueInlineObjectEvent.
00CD3E  1  28 41 CD         .byte $28,$41,$CD           ; $CD3E-$CD40
00CD41  1               
00CD41  1               Routine_CD41_Return:            ; $CD41
00CD41  1  60               rts                         ; $CD41: 60
00CD42  1               
00CD42  1               ; ============================================================================
00CD42  1               ; $CD42-$CD97
00CD42  1               ; Configure fields from the tables above, play a timed animation sequence,
00CD42  1               ; then restore state and leave through the common engine exit.
00CD42  1               ; ============================================================================
00CD42  1               
00CD42  1               RunSelectedStateAnimation:                   ; $CD42
00CD42  1  A6 72            ldx StateSelector           ; $CD42: A6 72
00CD44  1               
00CD44  1  E0 04            cpx #$04                    ; $CD44: E0 04
00CD46  1  D0 07            bne LoadStateAnimationParameters   ; $CD46: D0 07
00CD48  1               
00CD48  1               ; ----------------------------------------------------------------------------
00CD48  1               ; Special path for state four.
00CD48  1               ; ----------------------------------------------------------------------------
00CD48  1               
00CD48  1  A9 49            lda #$49                    ; $CD48: A9 49
00CD4A  1  8D B1 03         sta $03B1                   ; $CD4A: 8D B1 03
00CD4D  1               
00CD4D  1  D0 2C            bne WaitForStateAnimation       ; $CD4D: D0 2C
00CD4F  1                                               ; Always taken because A is nonzero.
00CD4F  1               
00CD4F  1               ; ----------------------------------------------------------------------------
00CD4F  1               ; Table-driven path for states zero through two.
00CD4F  1               ;
00CD4F  1               ; Y begins at $4C and is stored into $03B1.
00CD4F  1               ; ----------------------------------------------------------------------------
00CD4F  1               
00CD4F  1               LoadStateAnimationParameters:          ; $CD4F
00CD4F  1  A0 4C            ldy #$4C                    ; $CD4F: A0 4C
00CD51  1               
00CD51  1               
00CD51  1               StoreStateAnimationParameters: ; $CD51
00CD51  1  8C B1 03         sty $03B1 ; $CD51: 8C B1 03
00CD54  1               
00CD54  1  BD 21 CD         lda $CD21,x ; $CD54: BD 21 CD
00CD57  1  8D 0B 05         sta $050B ; $CD57: 8D 0B 05
00CD5A  1               
00CD5A  1  BD 24 CD         lda $CD24,x ; $CD5A: BD 24 CD
00CD5D  1  8D 0C 05         sta $050C ; $CD5D: 8D 0C 05
00CD60  1               
00CD60  1  BD 27 CD         lda $CD27,x ; $CD60: BD 27 CD
00CD63  1  8D 3C 05         sta $053C ; $CD63: 8D 3C 05
00CD66  1               
00CD66  1  BD 2A CD         lda $CD2A,x ; $CD66: BD 2A CD
00CD69  1  8D 3D 05         sta $053D ; $CD69: 8D 3D 05
00CD6C  1               ; ----------------------------------------------------------------------------
00CD6C  1               ; Run the indexed helper and wait for $60 ticks.
00CD6C  1               ; ----------------------------------------------------------------------------
00CD6C  1               
00CD6C  1  A2 02            ldx #$02                    ; $CD6C: A2 02
00CD6E  1  20 B7 E6         jsr ClearMovementTransforms                   ; $CD6E: 20 B7 E6
00CD71  1               
00CD71  1  A9 60            lda #$60                    ; $CD71: A9 60
00CD73  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $CD73: 20 41 EB
00CD76  1               
00CD76  1  A9 4B            lda #$4B                    ; $CD76: A9 4B
00CD78  1  8D B1 03         sta $03B1                   ; $CD78: 8D B1 03
00CD7B  1               
00CD7B  1               ; ----------------------------------------------------------------------------
00CD7B  1               ; Wait for $3C ticks.
00CD7B  1               ; ----------------------------------------------------------------------------
00CD7B  1               
00CD7B  1               WaitForStateAnimation:              ; $CD7B
00CD7B  1  A9 3C            lda #$3C                    ; $CD7B: A9 3C
00CD7D  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $CD7D: 20 41 EB
00CD80  1               
00CD80  1               ; ----------------------------------------------------------------------------
00CD80  1               ; Initialize indexed fields using inline data consumed by $C9A7.
00CD80  1               ;
00CD80  1               ; The first inline byte, $02, is metadata consumed by the return-address
00CD80  1               ; helper. The following four bytes initialize the indexed fields:
00CD80  1               ;
00CD80  1               ;   $00,$00,$C0,$F6
00CD80  1               ; ----------------------------------------------------------------------------
00CD80  1               
00CD80  1  20 A7 C9         jsr LoadObjectPositionInline
00CD83  1                                               ; $CD80: 20 A7 C9
00CD83  1               
00CD83  1  02               .byte $02                   ; $CD83: inline metadata/count
00CD84  1  00 00 C0 F6      .byte $00,$00,$C0,$F6       ; $CD84-$CD87: field data
00CD88  1               
00CD88  1               ; ----------------------------------------------------------------------------
00CD88  1               ; Run the indexed helper again and set the final animation/state value.
00CD88  1               ; ----------------------------------------------------------------------------
00CD88  1               
00CD88  1  A2 02            ldx #$02                    ; $CD88: A2 02
00CD8A  1  20 B7 E6         jsr ClearMovementTransforms                   ; $CD8A: 20 B7 E6
00CD8D  1               
00CD8D  1  A9 47            lda #$47                    ; $CD8D: A9 47
00CD8F  1  8D B1 03         sta $03B1                   ; $CD8F: 8D B1 03
00CD92  1               
00CD92  1  CE 96 05         dec $0596                   ; $CD92: CE 96 05
00CD95  1               
00CD95  1  4C 6A EB         jmp CommonEngineExit                   ; $CD95: 4C 6A EB
00CD98  1               
00CD98  1               ; ============================================================================
00CD98  1               ; $CD98-$CDA6
00CD98  1               ; Set state $6D to two, run state/action $2A, and leave through the common
00CD98  1               ; engine exit.
00CD98  1               ; ============================================================================
00CD98  1               
00CD98  1               StartHomeRunSequence:                   ; $CD98
00CD98  1  A9 02            lda #$02                    ; $CD98: A9 02
00CD9A  1  85 6D            sta SpecialSequenceState                     ; $CD9A: 85 6D
00CD9C  1               
00CD9C  1  A9 2A            lda #$2A                    ; $CD9C: A9 2A
00CD9E  1  20 11 CF         jsr AddTimedStateEvent                   ; $CD9E: 20 11 CF
00CDA1  1               
00CDA1  1  4C 6A EB         jmp CommonEngineExit                   ; $CDA1: 4C 6A EB
00CDA4  1               
00CDA4  1               ; ============================================================================
00CDA4  1               ; $CDA4-$CE19
00CDA4  1               ; Initialize state $6D, run an animation sequence, draw an encoded message,
00CDA4  1               ; and repeatedly copy palette/data bytes into the PPU command queue.
00CDA4  1               ; ============================================================================
00CDA4  1               
00CDA4  1               RunHomeRunCelebration:                   ; $CDA4
00CDA4  1  A9 01            lda #$01                    ; $CDA4: A9 01
00CDA6  1  85 FD            sta $FD                     ; $CDA6: 85 FD
00CDA8  1               
00CDA8  1  A9 04            lda #$04                    ; $CDA8: A9 04
00CDAA  1  85 6D            sta SpecialSequenceState                 ; $CDAA: 85 6D
00CDAC  1               
00CDAC  1               ; ----------------------------------------------------------------------------
00CDAC  1               ; Dispatch an inline command through QueueInlineObjectEvent.
00CDAC  1               ; ----------------------------------------------------------------------------
00CDAC  1               
00CDAC  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $CDAC: 20 0A EB
00CDAF  1               
00CDAF  1                   ; Inline command record consumed by QueueInlineObjectEvent.
00CDAF  1  15 D8 CD         .byte $15,$D8,$CD           ; $CDAF-$CDB1
00CDB2  1               
00CDB2  1               ; ----------------------------------------------------------------------------
00CDB2  1               ; Increment the current object's animation index twice.
00CDB2  1               ; ----------------------------------------------------------------------------
00CDB2  1               
00CDB2  1  A6 E1            ldx CurrentObjectIndex      ; $CDB2: A6 E1
00CDB4  1  20 38 E7         jsr ConvertObjectOffsetToDisplayIndex                   ; $CDB4: 20 38 E7
00CDB7  1               
00CDB7  1  FE 9A 03         inc $039A,x                 ; $CDB7: FE 9A 03
00CDBA  1  FE 9A 03         inc $039A,x                 ; $CDBA: FE 9A 03
00CDBD  1               
00CDBD  1               ; ----------------------------------------------------------------------------
00CDBD  1               ; Wait $14 ticks, increment the animation index once more, then wait again.
00CDBD  1               ; ----------------------------------------------------------------------------
00CDBD  1               
00CDBD  1               HomeRunAnimationLoop:     ; $CDBD
00CDBD  1  A9 14            lda #$14                    ; $CDBD: A9 14
00CDBF  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $CDBF: 20 41 EB
00CDC2  1               
00CDC2  1  A6 E1            ldx CurrentObjectIndex      ; $CDC2: A6 E1
00CDC4  1  20 38 E7         jsr ConvertObjectOffsetToDisplayIndex                   ; $CDC4: 20 38 E7
00CDC7  1               
00CDC7  1  FE 9A 03         inc $039A,x                 ; $CDC7: FE 9A 03
00CDCA  1               
00CDCA  1  A9 14            lda #$14                    ; $CDCA: A9 14
00CDCC  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $CDCC: 20 41 EB
00CDCF  1               
00CDCF  1               ; ----------------------------------------------------------------------------
00CDCF  1               ; Decrement the animation index. Repeat while the result is nonzero.
00CDCF  1               ; ----------------------------------------------------------------------------
00CDCF  1               
00CDCF  1  A6 E1            ldx CurrentObjectIndex      ; $CDCF: A6 E1
00CDD1  1  20 38 E7         jsr ConvertObjectOffsetToDisplayIndex                   ; $CDD1: 20 38 E7
00CDD4  1               
00CDD4  1  DE 9A 03         dec $039A,x                 ; $CDD4: DE 9A 03
00CDD7  1  D0 E4            bne HomeRunAnimationLoop
00CDD9  1                                               ; $CDD7: D0 E4
00CDD9  1               
00CDD9  1               ; ----------------------------------------------------------------------------
00CDD9  1               ; Draw an eight-character encoded message.
00CDD9  1               ; ----------------------------------------------------------------------------
00CDD9  1               
00CDD9  1  A9 20            lda #$20                    ; $CDD9: A9 20
00CDDB  1  A2 EC            ldx #$EC                    ; $CDDB: A2 EC
00CDDD  1  A0 08            ldy #$08                    ; $CDDD: A0 08
00CDDF  1  18               clc                         ; $CDDF: 18
00CDE0  1               
00CDE0  1  20 17 EA         jsr CopyInlineDisplayRecord                   ; $CDE0: 20 17 EA
00CDE3  1               
00CDE3  1  08               .byte $08                   ; $CDE3: character count
00CDE4  1  11 18 16 0E      .byte $11,$18,$16,$0E       ; $CDE4-$CDE7
00CDE8  1  25 1B 1E 17      .byte $25,$1B,$1E,$17       ; $CDE8-$CDEB
00CDEC  1               
00CDEC  1               ; ----------------------------------------------------------------------------
00CDEC  1               ; Set up the table-copy loop.
00CDEC  1               ; ----------------------------------------------------------------------------
00CDEC  1               
00CDEC  1               ResetCelebrationColorIndex:    ; $CDEC
00CDEC  1  A0 07            ldy #$07                    ; $CDEC: A0 07
00CDEE  1               
00CDEE  1               SaveCelebrationColorIndex:         ; $CDEE
00CDEE  1  84 70            sty $70                     ; $CDEE: 84 70
00CDF0  1               
00CDF0  1  A9 06            lda #$06                    ; $CDF0: A9 06
00CDF2  1  8D C6 05         sta $05C6                   ; $CDF2: 8D C6 05
00CDF5  1               
00CDF5  1               ; ----------------------------------------------------------------------------
00CDF5  1               ; Wait for six frames/ticks. Set bit 7 of $FE after each wait.
00CDF5  1               ; ----------------------------------------------------------------------------
00CDF5  1               
00CDF5  1               WaitCelebrationColorFrame:          ; $CDF5
00CDF5  1  20 48 EB         jsr SelectObjectEventBank1                   ; $CDF5: 20 48 EB
00CDF8  1               
00CDF8  1  A5 FE            lda PendingAudioFlags             ; $CDF8: A5 FE
00CDFA  1  09 80            ora #$80                    ; $CDFA: 09 80
00CDFC  1  85 FE            sta PendingAudioFlags             ; $CDFC: 85 FE
00CDFE  1               
00CDFE  1  CE C6 05         dec $05C6                   ; $CDFE: CE C6 05
00CE01  1  D0 F2            bne WaitCelebrationColorFrame   ; $CE01: D0 F2
00CE03  1               
00CE03  1               ; ----------------------------------------------------------------------------
00CE03  1               ; Start a one-byte PPU command.
00CE03  1               ; ----------------------------------------------------------------------------
00CE03  1               
00CE03  1  A9 3F            lda #$3F                    ; $CE03: A9 3F
00CE05  1  A2 07            ldx #$07                    ; $CE05: A2 07
00CE07  1  A0 01            ldy #$01                    ; $CE07: A0 01
00CE09  1  18               clc                         ; $CE09: 18
00CE0A  1               
00CE0A  1  20 3E EA         jsr AllocateDisplayBufferRecord                   ; $CE0A: 20 3E EA
00CE0D  1               
00CE0D  1               ; ----------------------------------------------------------------------------
00CE0D  1               ; Append one byte from the table at $CE1A.
00CE0D  1               ; ----------------------------------------------------------------------------
00CE0D  1               
00CE0D  1  A4 70            ldy TableCopyIndex          ; $CE0D: A4 70
00CE0F  1               
00CE0F  1  B9 1A CE         lda CelebrationPaletteSequence,y            ; $CE0F: B9 1A CE
00CE12  1  9D 00 03         sta $0300,x                 ; $CE12: 9D 00 03
00CE15  1               
00CE15  1  88               dey                         ; $CE15: 88
00CE16  1  10 D6            bpl SaveCelebrationColorIndex  ; $CE16: 10 D6
00CE18  1               
00CE18  1  30 D2            bmi ResetCelebrationColorIndex
00CE1A  1                                               ; $CE18: 30 D2
00CE1A  1                                               ; Always taken after Y becomes negative.
00CE1A  1               
00CE1A  1               ; ============================================================================
00CE1A  1               ; $CE1A-$CE21
00CE1A  1               ; Eight-byte lookup table used by the loop above.
00CE1A  1               ; ============================================================================
00CE1A  1               
00CE1A  1               CelebrationPaletteSequence:                     ; $CE1A
00CE1A  1  30 21 33 24      .byte $30,$21,$33,$24
00CE1E  1  36 27 39 2A      .byte $36,$27,$39,$2A
00CE22  1               
00CE22  1               ; ============================================================================
00CE22  1               ; $CE22-$CE31
00CE22  1               ; Clear active state, advance $45, process event slot $11, then leave through
00CE22  1               ; command $08.
00CE22  1               ; ============================================================================
00CE22  1               
00CE22  1               ; ----------------------------------------------------------------------------
00CE22  1               ; Contract:
00CE22  1               ;   Description: Implements Finish State Progression.
00CE22  1               ;   Entry: Registers: A
00CE22  1               ;   Returns/products: Registers/clobbers: A, X, Y
00CE22  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00CE22  1               ;   Memory effects: basemotionactive
00CE22  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00CE22  1               ;          comparison, load, or store path and are not a stable API product.
00CE22  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 2.
00CE22  1               ; ----------------------------------------------------------------------------
00CE22  1               FinishStateProgression:                   ; $CE22
00CE22  1  A9 00            lda #$00                    ; $CE22: A9 00
00CE24  1  85 5C            sta BaseMotionActive            ; $CE24: 85 5C
00CE26  1               
00CE26  1  E6 45            inc MatchCompleteFlag             ; $CE26: E6 45
00CE28  1               
00CE28  1  A0 11            ldy #$11                    ; $CE28: A0 11
00CE2A  1  20 66 EB         jsr DispatchNextQueuedEvent                   ; $CE2A: 20 66 EB
00CE2D  1               
00CE2D  1  A2 08            ldx #$08                    ; $CE2D: A2 08
00CE2F  1  4C 2A EB         jmp ProcessQueuedObjectEvent                   ; $CE2F: 4C 2A EB
00CE32  1               
00CE32  1               ; ============================================================================
00CE32  1               ; $CE32-$CEA4
00CE32  1               ; Search a timing/state table, map selected values to flags, display the
00CE32  1               ; corresponding message, and loop until the state condition is complete.
00CE32  1               ; ============================================================================
00CE32  1               
00CE32  1               RunEventAnnouncementLoop:                   ; $CE32
00CE32  1  A9 00            lda #$00                    ; $CE32: A9 00
00CE34  1  85 6F            sta PendingEvent            ; $CE34: 85 6F
00CE36  1               
00CE36  1               ReloadAnnouncementDelay:         ; $CE36
00CE36  1  A9 01            lda #$01                    ; $CE36: A9 01
00CE38  1               
00CE38  1               WaitAnnouncementDelay:              ; $CE38
00CE38  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $CE38: 20 41 EB
00CE3B  1               
00CE3B  1               ; ----------------------------------------------------------------------------
00CE3B  1               ; Compare the current index in $6A with the limit in $69.
00CE3B  1               ; If equal, restart the search from its initial state.
00CE3B  1               ; ----------------------------------------------------------------------------
00CE3B  1               
00CE3B  1  A6 6A            ldx EventReadIndex          ; $CE3B: A6 6A
00CE3D  1  E4 69            cpx EventWriteIndex         ; $CE3D: E4 69
00CE3F  1  F0 F1            beq RunEventAnnouncementLoop            ; $CE3F: F0 F1
00CE41  1               
00CE41  1  CA               dex                         ; $CE41: CA
00CE42  1  10 02            bpl FindReadyAnnouncement ; $CE42: 10 02
00CE44  1               
00CE44  1  A2 03            ldx #$03                    ; $CE44: A2 03
00CE46  1               
00CE46  1               ; ----------------------------------------------------------------------------
00CE46  1               ; Search backward for a zero timer/state entry in $05AD-$05B0.
00CE46  1               ; Nonzero entries return to $CE36, reloading the delay value with one.
00CE46  1               ; ----------------------------------------------------------------------------
00CE46  1               
00CE46  1               FindReadyAnnouncement:        ; $CE46
00CE46  1  BD AD 05         lda $05AD,x                 ; $CE46: BD AD 05
00CE49  1  D0 EB            bne ReloadAnnouncementDelay  ; $CE49: D0 EB
00CE4B  1               
00CE4B  1  86 6A            stx EventReadIndex          ; $CE4B: 86 6A
00CE4D  1  E6 6F            inc PendingEvent            ; $CE4D: E6 6F
00CE4F  1               
00CE4F  1  BD A9 05         lda $05A9,x                 ; $CE4F: BD A9 05
00CE52  1  8D BA 05         sta $05BA                   ; $CE52: 8D BA 05
00CE55  1               
00CE55  1               ; ----------------------------------------------------------------------------
00CE55  1               ; Wait one frame and retrieve the selected table value.
00CE55  1               ; ----------------------------------------------------------------------------
00CE55  1               
00CE55  1  20 48 EB         jsr SelectObjectEventBank1                   ; $CE55: 20 48 EB
00CE58  1               
00CE58  1  AC BA 05         ldy $05BA                   ; $CE58: AC BA 05
00CE5B  1               
00CE5B  1  C0 3C            cpy #$3C                    ; $CE5B: C0 3C
00CE5D  1  D0 12            bne MapAnnouncementToAudioFlag   ; $CE5D: D0 12
00CE5F  1               
00CE5F  1               ; ----------------------------------------------------------------------------
00CE5F  1               ; Special handling for value $3C.
00CE5F  1               ; ----------------------------------------------------------------------------
00CE5F  1               
00CE5F  1  A5 69            lda EventWriteIndex         ; $CE5F: A5 69
00CE61  1  85 6A            sta EventReadIndex          ; $CE61: 85 6A
00CE63  1               
00CE63  1  A5 33            lda RoundStateIndex            ; $CE63: A5 33
00CE65  1  C9 10            cmp #$10                    ; $CE65: C9 10
00CE67  1  90 08            bcc MapAnnouncementToAudioFlag   ; $CE67: 90 08
00CE69  1               
00CE69  1  D0 31            bne DisplayBlankAnnouncement
00CE6B  1                                               ; $CE69: D0 31
00CE6B  1               
00CE6B  1  A5 67            lda PlayerOneScore            ; $CE6B: A5 67
00CE6D  1  C5 68            cmp PlayerTwoScore            ; $CE6D: C5 68
00CE6F  1  90 2B            bcc DisplayBlankAnnouncement
00CE71  1                                               ; $CE6F: 90 2B
00CE71  1               
00CE71  1               ; ----------------------------------------------------------------------------
00CE71  1               ; Map selected Y values to a bit/flag value in X.
00CE71  1               ; ----------------------------------------------------------------------------
00CE71  1               
00CE71  1               MapAnnouncementToAudioFlag:          ; $CE71
00CE71  1  A2 00            ldx #$00                    ; $CE71: A2 00
00CE73  1               
00CE73  1  C0 06            cpy #$06                    ; $CE73: C0 06
00CE75  1  D0 02            bne CheckAnnouncement12            ; $CE75: D0 02
00CE77  1               
00CE77  1  A2 08            ldx #$08                    ; $CE77: A2 08
00CE79  1               
00CE79  1               CheckAnnouncement12:                   ; $CE79
00CE79  1  C0 12            cpy #$12                    ; $CE79: C0 12
00CE7B  1  D0 02            bne CheckAnnouncement42            ; $CE7B: D0 02
00CE7D  1               
00CE7D  1  A2 01            ldx #$01                    ; $CE7D: A2 01
00CE7F  1               
00CE7F  1               CheckAnnouncement42:                   ; $CE7F
00CE7F  1  C0 42            cpy #$42                    ; $CE7F: C0 42
00CE81  1  D0 02            bne CheckAnnouncement0C            ; $CE81: D0 02
00CE83  1               
00CE83  1  A2 02            ldx #$02                    ; $CE83: A2 02
00CE85  1               
00CE85  1               CheckAnnouncement0C:                   ; $CE85
00CE85  1  C0 0C            cpy #$0C                    ; $CE85: C0 0C
00CE87  1  D0 02            bne CheckAnnouncement18            ; $CE87: D0 02
00CE89  1               
00CE89  1  A2 10            ldx #$10                    ; $CE89: A2 10
00CE8B  1               
00CE8B  1               CheckAnnouncement18:                   ; $CE8B
00CE8B  1  C0 18            cpy #$18                    ; $CE8B: C0 18
00CE8D  1  D0 02            bne SaveAnnouncementAudioFlag   ; $CE8D: D0 02
00CE8F  1               
00CE8F  1  A2 08            ldx #$08                    ; $CE8F: A2 08
00CE91  1               
00CE91  1               SaveAnnouncementAudioFlag:          ; $CE91
00CE91  1  86 FE            stx PendingAudioFlags             ; $CE91: 86 FE
00CE93  1               
00CE93  1  98               tya                         ; $CE93: 98
00CE94  1  20 A5 CE         jsr DisplayAnnouncementPair
00CE97  1                                               ; $CE94: 20 A5 CE
00CE97  1               
00CE97  1  A9 3C            lda #$3C                    ; $CE97: A9 3C
00CE99  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $CE99: 20 41 EB
00CE9C  1               
00CE9C  1               ; ----------------------------------------------------------------------------
00CE9C  1               ; Display the default message.
00CE9C  1               ; ----------------------------------------------------------------------------
00CE9C  1               
00CE9C  1               DisplayBlankAnnouncement:    ; $CE9C
00CE9C  1  A9 00            lda #$00                    ; $CE9C: A9 00
00CE9E  1  20 A5 CE         jsr DisplayAnnouncementPair
00CEA1  1                                               ; $CE9E: 20 A5 CE
00CEA1  1               
00CEA1  1               ; ----------------------------------------------------------------------------
00CEA1  1               ; Continue at the wait call without reloading A with one.
00CEA1  1               ;
00CEA1  1               ; This distinct target is required for the original D0 93 branch operand:
00CEA1  1               ;
00CEA1  1               ;   $CEA3: D0 93 -> $CE38
00CEA1  1               ; ----------------------------------------------------------------------------
00CEA1  1               
00CEA1  1  A9 05            lda #$05                    ; $CEA1: A9 05
00CEA3  1  D0 93            bne WaitAnnouncementDelay       ; $CEA3: D0 93
00CEA5  1                                               ; Always taken because A is nonzero.
00CEA5  1               
00CEA5  1               ; ============================================================================
00CEA5  1               ; $CEA5-$CEC8
00CEA5  1               ; Queue a six-byte encoded message selected by A.
00CEA5  1               ;
00CEA5  1               ; Entry:
00CEA5  1               ;   A = offset into the encoded text table at $CEC9.
00CEA5  1               ; ============================================================================
00CEA5  1               
00CEA5  1               DisplayAnnouncementPair:    ; $CEA5
00CEA5  1  48               pha                         ; $CEA5: 48
00CEA6  1               
00CEA6  1  A0 23            ldy #$23                    ; $CEA6: A0 23
00CEA8  1  20 AE CE         jsr QueueAnnouncementText            ; $CEA8: 20 AE CE
00CEAB  1               
00CEAB  1  68               pla                         ; $CEAB: 68
00CEAC  1               
00CEAC  1               ; ----------------------------------------------------------------------------
00CEAC  1               ; Secondary entry point.
00CEAC  1               ;
00CEAC  1               ; Entry:
00CEAC  1               ;   A = text-table offset.
00CEAC  1               ;   The destination selector is changed to $2B.
00CEAC  1               ; ----------------------------------------------------------------------------
00CEAC  1               
00CEAC  1               DisplaySecondaryAnnouncement:                   ; $CEAC
00CEAC  1  A0 2B            ldy #$2B                    ; $CEAC: A0 2B
00CEAE  1               
00CEAE  1               ; ----------------------------------------------------------------------------
00CEAE  1               ; Contract:
00CEAE  1               ;   Description: Queues Announcement Text.
00CEAE  1               ;   Entry: Registers: A, X, Y; Memory: announcementtexttable
00CEAE  1               ;   Returns/products: Registers/clobbers: A, X, Y
00CEAE  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00CEAE  1               ;   Memory effects: textcopycount, $0300
00CEAE  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00CEAE  1               ;          comparison, load, or store path and are not a stable API product.
00CEAE  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00CEAE  1               ; ----------------------------------------------------------------------------
00CEAE  1               QueueAnnouncementText:                   ; $CEAE
00CEAE  1  48               pha                         ; $CEAE: 48
00CEAF  1  18               clc                         ; $CEAF: 18
00CEB0  1               
00CEB0  1  98               tya                         ; $CEB0: 98
00CEB1  1  A2 37            ldx #$37                    ; $CEB1: A2 37
00CEB3  1  A0 06            ldy #$06                    ; $CEB3: A0 06
00CEB5  1               
00CEB5  1  84 6B            sty TextCopyCount           ; $CEB5: 84 6B
00CEB7  1               
00CEB7  1  20 3E EA         jsr AllocateDisplayBufferRecord                   ; $CEB7: 20 3E EA
00CEBA  1               
00CEBA  1  68               pla                         ; $CEBA: 68
00CEBB  1  A8               tay                         ; $CEBB: A8
00CEBC  1               
00CEBC  1               CopyAnnouncementText:          ; $CEBC
00CEBC  1  B9 C9 CE         lda AnnouncementTextTable,y             ; $CEBC: B9 C9 CE
00CEBF  1  9D 00 03         sta $0300,x                 ; $CEBF: 9D 00 03
00CEC2  1               
00CEC2  1  C8               iny                         ; $CEC2: C8
00CEC3  1  E8               inx                         ; $CEC3: E8
00CEC4  1               
00CEC4  1  C6 6B            dec TextCopyCount           ; $CEC4: C6 6B
00CEC6  1  D0 F4            bne CopyAnnouncementText   ; $CEC6: D0 F4
00CEC8  1               
00CEC8  1  60               rts                         ; $CEC8: 60
00CEC9  1               
00CEC9  1               ; ============================================================================
00CEC9  1               ; Encoded text/data table begins at CPU $CEC9.
00CEC9  1               ; ============================================================================
00CEC9  1               
00CEC9  1               ; ============================================================================
00CEC9  1               ; $CEC9-$CF10
00CEC9  1               ; Encoded six-character message table.
00CEC9  1               ;
00CEC9  1               ; Routine $CEA5 selects an entry by passing an offset in A, then copies six
00CEC9  1               ; bytes beginning at AnnouncementTextTable + A.
00CEC9  1               ;
00CEC9  1               ; Known offsets used by the preceding routine include:
00CEC9  1               ;
00CEC9  1               ;   $00, $06, $0C, $12, $18, $1E, $24, $2A, $30, $36, $3C, $42
00CEC9  1               ;
00CEC9  1               ; Each entry is exactly six bytes.
00CEC9  1               ; ============================================================================
00CEC9  1               
00CEC9  1               AnnouncementTextTable:                      ; $CEC9
00CEC9  1               
00CEC9  1               AnnouncementTextBlank:              ; $CEC9, offset $00
00CEC9  1  25 25 25 25      .byte $25,$25,$25,$25,$25,$25
00CECD  1  25 25        
00CECF  1               
00CECF  1               AnnouncementTextFoul:              ; $CECF, offset $06
00CECF  1  25 0F 18 1E      .byte $25,$0F,$18,$1E,$15,$25
00CED3  1  15 25        
00CED5  1               
00CED5  1               AnnouncementTextStrike:              ; $CED5, offset $0C
00CED5  1  1C 1D 1B 12      .byte $1C,$1D,$1B,$12,$14,$0E
00CED9  1  14 0E        
00CEDB  1               
00CEDB  1               AnnouncementTextOut:              ; $CEDB, offset $12
00CEDB  1  25 18 1E 1D      .byte $25,$18,$1E,$1D,$25,$25
00CEDF  1  25 25        
00CEE1  1               
00CEE1  1               AnnouncementTextBall:              ; $CEE1, offset $18
00CEE1  1  25 0B 0A 15      .byte $25,$0B,$0A,$15,$15,$25
00CEE5  1  15 25        
00CEE7  1               
00CEE7  1               AnnouncementTextWalk:              ; $CEE7, offset $1E
00CEE7  1  25 20 0A 15      .byte $25,$20,$0A,$15,$14,$25
00CEEB  1  14 25        
00CEED  1               
00CEED  1               AnnouncementTextSingle:              ; $CEED, offset $24
00CEED  1  1C 12 17 10      .byte $1C,$12,$17,$10,$15,$0E
00CEF1  1  15 0E        
00CEF3  1               
00CEF3  1               AnnouncementTextTwoBase:              ; $CEF3, offset $2A
00CEF3  1  02 25 0B 0A      .byte $02,$25,$0B,$0A,$1C,$0E
00CEF7  1  1C 0E        
00CEF9  1               
00CEF9  1               AnnouncementTextThreeBase:              ; $CEF9, offset $30
00CEF9  1  03 25 0B 0A      .byte $03,$25,$0B,$0A,$1C,$0E
00CEFD  1  1C 0E        
00CEFF  1               
00CEFF  1               AnnouncementTextDeadBall:              ; $CEFF, offset $36
00CEFF  1  0D 25 0B 0A      .byte $0D,$25,$0B,$0A,$15,$15
00CF03  1  15 15        
00CF05  1               
00CF05  1               AnnouncementTextChange:              ; $CF05, offset $3C
00CF05  1  0C 11 0A 17      .byte $0C,$11,$0A,$17,$10,$0E
00CF09  1  10 0E        
00CF0B  1               
00CF0B  1               AnnouncementTextSafe:              ; $CF0B, offset $42
00CF0B  1  25 1C 0A 0F      .byte $25,$1C,$0A,$0F,$0E,$25
00CF0F  1  0E 25        
00CF11  1               
00CF11  1               ; ============================================================================
00CF11  1               ; $CF11-$CF22
00CF11  1               ; Move backward through a four-entry circular index and initialize the
00CF11  1               ; corresponding timer/state fields.
00CF11  1               ;
00CF11  1               ; Input:
00CF11  1               ;   A = value stored into $05A9,X
00CF11  1               ;
00CF11  1               ; Operation:
00CF11  1               ;   Decrement $69, wrapping from $00 to $03.
00CF11  1               ;   Store the caller-supplied A value into $05A9,X.
00CF11  1               ;   Initialize $05AD,X to $14.
00CF11  1               ;
00CF11  1               ; Output:
00CF11  1               ;   X = updated index
00CF11  1               ;   $69 = updated index
00CF11  1               ; ============================================================================
00CF11  1               
00CF11  1               ; ----------------------------------------------------------------------------
00CF11  1               ; Contract:
00CF11  1               ;   Description: Implements Add Timed State Event.
00CF11  1               ;   Entry: Registers: A, X; Memory: eventwriteindex
00CF11  1               ;   Returns/products: Registers/clobbers: A, X
00CF11  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00CF11  1               ;   Memory effects: eventwriteindex, $05a9, $05ad
00CF11  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00CF11  1               ;          comparison, load, or store path and are not a stable API product.
00CF11  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 9.
00CF11  1               ; ----------------------------------------------------------------------------
00CF11  1               AddTimedStateEvent:             ; $CF11
00CF11  1  A6 69            ldx EventWriteIndex         ; $CF11: A6 69
00CF13  1               
00CF13  1  CA               dex                         ; $CF13: CA
00CF14  1  10 02            bpl Routine_CF18_SaveIndex  ; $CF14: 10 02
00CF16  1               
00CF16  1  A2 03            ldx #$03                    ; $CF16: A2 03
00CF18  1                                               ; Wrap the index from zero to three.
00CF18  1               
00CF18  1               Routine_CF18_SaveIndex:         ; $CF18
00CF18  1  86 69            stx EventWriteIndex         ; $CF18: 86 69
00CF1A  1               
00CF1A  1  9D A9 05         sta $05A9,x                 ; $CF1A: 9D A9 05
00CF1D  1                                               ; Store the caller-supplied state value.
00CF1D  1               
00CF1D  1  A9 14            lda #$14                    ; $CF1D: A9 14
00CF1F  1  9D AD 05         sta $05AD,x                 ; $CF1F: 9D AD 05
00CF22  1                                               ; Initialize the associated timer.
00CF22  1               
00CF22  1  60               rts                         ; $CF22: 60
00CF23  1               
00CF23  1               ; ============================================================================
00CF23  1               ; $CF23-$CF44
00CF23  1               ; Select a state-dependent value, construct a one-byte PPU queue entry,
00CF23  1               ; and append tile/data byte $AE.
00CF23  1               ;
00CF23  1               ; Two entry points exist:
00CF23  1               ;
00CF23  1               ;   $CF23 derives a value from $62 using base $22.
00CF23  1               ;   $CF2A derives a value from $64 using base $42.
00CF23  1               ;
00CF23  1               ; Both paths continue through $CF2F.
00CF23  1               ; ============================================================================
00CF23  1               
00CF23  1               ; ----------------------------------------------------------------------------
00CF23  1               ; Contract:
00CF23  1               ;   Description: Queues Primary State Marker.
00CF23  1               ;   Entry: Registers: A; Memory: primarysequencestate, secondarysequencestate
00CF23  1               ;   Returns/products: Registers/clobbers: A, X, Y
00CF23  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00CF23  1               ;   Memory effects: $0300
00CF23  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00CF23  1               ;          comparison, load, or store path and are not a stable API product.
00CF23  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 2.
00CF23  1               ; ----------------------------------------------------------------------------
00CF23  1               QueuePrimaryStateMarker:                   ; $CF23
00CF23  1  18               clc                         ; $CF23: 18
00CF24  1               
00CF24  1  A9 22            lda #$22                    ; $CF24: A9 22
00CF26  1  65 62            adc PrimarySequenceState                 ; $CF26: 65 62
00CF28  1               
00CF28  1  D0 05            bne BuildStateMarkerEntries ; $CF28: D0 05
00CF2A  1                                               ; Always taken unless the addition wraps
00CF2A  1                                               ; exactly to zero.
00CF2A  1               
00CF2A  1               ; ----------------------------------------------------------------------------
00CF2A  1               ; Secondary entry point used by callers that derive the value from $64.
00CF2A  1               ; ----------------------------------------------------------------------------
00CF2A  1               
00CF2A  1               ; ----------------------------------------------------------------------------
00CF2A  1               ; Contract:
00CF2A  1               ;   Description: Queues Secondary State Marker.
00CF2A  1               ;   Entry: Registers: A; Memory: secondarysequencestate
00CF2A  1               ;   Returns/products: Registers/clobbers: A, X, Y
00CF2A  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00CF2A  1               ;   Memory effects: $0300
00CF2A  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00CF2A  1               ;          comparison, load, or store path and are not a stable API product.
00CF2A  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 2.
00CF2A  1               ; ----------------------------------------------------------------------------
00CF2A  1               QueueSecondaryStateMarker:                   ; $CF2A
00CF2A  1  18               clc                         ; $CF2A: 18
00CF2B  1               
00CF2B  1  A9 42            lda #$42                    ; $CF2B: A9 42
00CF2D  1  65 64            adc SecondarySequenceState                 ; $CF2D: 65 64
00CF2F  1               
00CF2F  1               ; ----------------------------------------------------------------------------
00CF2F  1               ; Preserve the calculated value, perform the first setup call, then use the
00CF2F  1               ; saved value as X for the PPU queue helper.
00CF2F  1               ; ----------------------------------------------------------------------------
00CF2F  1               
00CF2F  1               ; ----------------------------------------------------------------------------
00CF2F  1               ; Contract:
00CF2F  1               ;   Description: Implements Build State Marker Entries.
00CF2F  1               ;   Entry: Registers: A
00CF2F  1               ;   Returns/products: Registers/clobbers: A, X, Y
00CF2F  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00CF2F  1               ;   Memory effects: $0300
00CF2F  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00CF2F  1               ;          comparison, load, or store path and are not a stable API product.
00CF2F  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00CF2F  1               ; ----------------------------------------------------------------------------
00CF2F  1               BuildStateMarkerEntries:        ; $CF2F
00CF2F  1  48               pha                         ; $CF2F: 48
00CF30  1  AA               tax                         ; $CF30: AA
00CF31  1               
00CF31  1  A9 23            lda #$23                    ; $CF31: A9 23
00CF33  1  20 3A CF         jsr QueueStateMarkerEntry            ; $CF33: 20 3A CF
00CF36  1               
00CF36  1  68               pla                         ; $CF36: 68
00CF37  1  AA               tax                         ; $CF37: AA
00CF38  1               
00CF38  1  A9 2B            lda #$2B                    ; $CF38: A9 2B
00CF3A  1               
00CF3A  1               ; ----------------------------------------------------------------------------
00CF3A  1               ; Secondary helper entry.
00CF3A  1               ;
00CF3A  1               ; Entry:
00CF3A  1               ;   A = destination selector/address component
00CF3A  1               ;   X = state-derived coordinate/index
00CF3A  1               ;
00CF3A  1               ; Queue one data byte and append $AE.
00CF3A  1               ; ----------------------------------------------------------------------------
00CF3A  1               
00CF3A  1               ; ----------------------------------------------------------------------------
00CF3A  1               ; Contract:
00CF3A  1               ;   Description: Queues State Marker Entry.
00CF3A  1               ;   Entry: Registers: A
00CF3A  1               ;   Returns/products: Registers/clobbers: A, Y
00CF3A  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00CF3A  1               ;   Memory effects: $0300
00CF3A  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00CF3A  1               ;          comparison, load, or store path and are not a stable API product.
00CF3A  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00CF3A  1               ; ----------------------------------------------------------------------------
00CF3A  1               QueueStateMarkerEntry:                   ; $CF3A
00CF3A  1  A0 01            ldy #$01                    ; $CF3A: A0 01
00CF3C  1               
00CF3C  1  20 3E EA         jsr AllocateDisplayBufferRecord                   ; $CF3C: 20 3E EA
00CF3F  1               
00CF3F  1  A9 AE            lda #$AE                    ; $CF3F: A9 AE
00CF41  1  9D 00 03         sta $0300,x                 ; $CF41: 9D 00 03
00CF44  1               
00CF44  1  60               rts                         ; $CF44: 60
00CF45  1               
00CF45  1               ; ============================================================================
00CF45  1               ; $CF45-$CF66
00CF45  1               ; Queue two related three-character display fields.
00CF45  1               ;
00CF45  1               ; Entry points:
00CF45  1               ;   $CF45 queues fields using selectors $43 and $23.
00CF45  1               ;   $CF4A queues only the field using selector $23.
00CF45  1               ;   $CF51 accepts a selector in A.
00CF45  1               ;   $CF5C performs the final three-character blank-field write.
00CF45  1               ; ============================================================================
00CF45  1               
00CF45  1               ; ----------------------------------------------------------------------------
00CF45  1               ; Contract:
00CF45  1               ;   Description: Clears or resets Both State Fields.
00CF45  1               ;   Entry: Registers: A
00CF45  1               ;   Returns/products: Registers/clobbers: A, X, Y; Flags: condition flags may carry result state
00CF45  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00CF45  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00CF45  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00CF45  1               ;          comparison, load, or store path and are not a stable API product.
00CF45  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00CF45  1               ; ----------------------------------------------------------------------------
00CF45  1               ClearBothStateFields:                   ; $CF45
00CF45  1  A9 43            lda #$43                    ; $CF45: A9 43
00CF47  1  20 51 CF         jsr ClearStateFieldPair            ; $CF47: 20 51 CF
00CF4A  1               
00CF4A  1               ; ----------------------------------------------------------------------------
00CF4A  1               ; Secondary entry point.
00CF4A  1               ; ----------------------------------------------------------------------------
00CF4A  1               
00CF4A  1               ; ----------------------------------------------------------------------------
00CF4A  1               ; Contract:
00CF4A  1               ;   Description: Clears or resets Primary State Field.
00CF4A  1               ;   Entry: Registers: A
00CF4A  1               ;   Returns/products: Registers/clobbers: A, X, Y; Flags: condition flags may carry result state
00CF4A  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00CF4A  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00CF4A  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00CF4A  1               ;          comparison, load, or store path and are not a stable API product.
00CF4A  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 3.
00CF4A  1               ; ----------------------------------------------------------------------------
00CF4A  1               ClearPrimaryStateField:                   ; $CF4A
00CF4A  1  A9 23            lda #$23                    ; $CF4A: A9 23
00CF4C  1  20 51 CF         jsr ClearStateFieldPair            ; $CF4C: 20 51 CF
00CF4F  1               
00CF4F  1  A9 03            lda #$03                    ; $CF4F: A9 03
00CF51  1               
00CF51  1               ; ----------------------------------------------------------------------------
00CF51  1               ; Preserve the caller-supplied value in A and X.
00CF51  1               ;
00CF51  1               ; The first blank field uses destination selector $23.
00CF51  1               ; ----------------------------------------------------------------------------
00CF51  1               
00CF51  1               ; ----------------------------------------------------------------------------
00CF51  1               ; Contract:
00CF51  1               ;   Description: Clears or resets State Field Pair.
00CF51  1               ;   Entry: Registers: A
00CF51  1               ;   Returns/products: Registers/clobbers: A, X, Y; Flags: condition flags may carry result state
00CF51  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00CF51  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00CF51  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00CF51  1               ;          comparison, load, or store path and are not a stable API product.
00CF51  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 5.
00CF51  1               ; ----------------------------------------------------------------------------
00CF51  1               ClearStateFieldPair:                   ; $CF51
00CF51  1  48               pha                         ; $CF51: 48
00CF52  1  AA               tax                         ; $CF52: AA
00CF53  1               
00CF53  1  A9 23            lda #$23                    ; $CF53: A9 23
00CF55  1  20 5C CF         jsr QueueThreeBlanks            ; $CF55: 20 5C CF
00CF58  1               
00CF58  1  68               pla                         ; $CF58: 68
00CF59  1  AA               tax                         ; $CF59: AA
00CF5A  1               
00CF5A  1  A9 2B            lda #$2B                    ; $CF5A: A9 2B
00CF5C  1               
00CF5C  1               ; ----------------------------------------------------------------------------
00CF5C  1               ; Queue a three-character blank field.
00CF5C  1               ;
00CF5C  1               ; Entry:
00CF5C  1               ;   A = destination selector/address component
00CF5C  1               ;   X = caller-supplied coordinate or index
00CF5C  1               ;
00CF5C  1               ; The routine at $EA17 consumes the four inline bytes following the JSR:
00CF5C  1               ; one length byte followed by three encoded blank characters.
00CF5C  1               ; ----------------------------------------------------------------------------
00CF5C  1               
00CF5C  1               ; ----------------------------------------------------------------------------
00CF5C  1               ; Contract:
00CF5C  1               ;   Description: Queues Three Blanks.
00CF5C  1               ;   Entry: No register input inferred
00CF5C  1               ;   Returns/products: Registers/clobbers: Y; Flags: condition flags may carry result state
00CF5C  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00CF5C  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00CF5C  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00CF5C  1               ;          comparison, load, or store path and are not a stable API product.
00CF5C  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00CF5C  1               ; ----------------------------------------------------------------------------
00CF5C  1               QueueThreeBlanks:                   ; $CF5C
00CF5C  1  A0 03            ldy #$03                    ; $CF5C: A0 03
00CF5E  1  18               clc                         ; $CF5E: 18
00CF5F  1               
00CF5F  1  20 17 EA         jsr CopyInlineDisplayRecord                   ; $CF5F: 20 17 EA
00CF62  1               
00CF62  1  03               .byte $03                   ; $CF62: character count
00CF63  1  25 25 25         .byte $25,$25,$25           ; $CF63-$CF65
00CF66  1               
00CF66  1  60               rts                         ; $CF66: 60
00CF67  1               
00CF67  1               ; ============================================================================
00CF67  1               ; $CF67-$CF8A
00CF67  1               ; Build a four-byte PPU queue entry using the current state in $33.
00CF67  1               ;
00CF67  1               ; The helper at $EA3E creates a four-byte queue record and returns its data
00CF67  1               ; position in X. This routine then fills the record with values derived from
00CF67  1               ; $33.
00CF67  1               ; ============================================================================
00CF67  1               
00CF67  1               ; ----------------------------------------------------------------------------
00CF67  1               ; Contract:
00CF67  1               ;   Description: Queues Round Number Display.
00CF67  1               ;   Entry: Registers: A, Y; Memory: roundstateindex
00CF67  1               ;   Returns/products: Registers/clobbers: A, X, Y
00CF67  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00CF67  1               ;   Memory effects: $0300, $0301, $0302, $0303
00CF67  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00CF67  1               ;          comparison, load, or store path and are not a stable API product.
00CF67  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00CF67  1               ; ----------------------------------------------------------------------------
00CF67  1               QueueRoundNumberDisplay:                   ; $CF67
00CF67  1  A9 2A            lda #$2A                    ; $CF67: A9 2A
00CF69  1  A2 82            ldx #$82                    ; $CF69: A2 82
00CF6B  1  A0 04            ldy #$04                    ; $CF6B: A0 04
00CF6D  1  18               clc                         ; $CF6D: 18
00CF6E  1               
00CF6E  1  20 3E EA         jsr AllocateDisplayBufferRecord                   ; $CF6E: 20 3E EA
00CF71  1               
00CF71  1               ; ----------------------------------------------------------------------------
00CF71  1               ; Derive the first byte from half of $33, rounded upward.
00CF71  1               ;
00CF71  1               ;   Y = ($33 >> 1) + 1
00CF71  1               ; ----------------------------------------------------------------------------
00CF71  1               
00CF71  1  A5 33            lda RoundStateIndex            ; $CF71: A5 33
00CF73  1  4A               lsr                         ; $CF73: 4A
00CF74  1  A8               tay                         ; $CF74: A8
00CF75  1  C8               iny                         ; $CF75: C8
00CF76  1               
00CF76  1  98               tya                         ; $CF76: 98
00CF77  1  9D 00 03         sta $0300,x                 ; $CF77: 9D 00 03
00CF7A  1               
00CF7A  1               ; ----------------------------------------------------------------------------
00CF7A  1               ; Store $3B as the second byte.
00CF7A  1               ;
00CF7A  1               ; Carry remains clear from the preceding LSR because $33 is expected to be
00CF7A  1               ; even or within the state range used by this routine.
00CF7A  1               ; ----------------------------------------------------------------------------
00CF7A  1               
00CF7A  1  A9 3B            lda #$3B                    ; $CF7A: A9 3B
00CF7C  1  9D 01 03         sta $0301,x                 ; $CF7C: 9D 01 03
00CF7F  1               
00CF7F  1               ; ----------------------------------------------------------------------------
00CF7F  1               ; Calculate the third byte:
00CF7F  1               ;
00CF7F  1               ;   (($3B - $1C) << 1) = $3E
00CF7F  1               ;
00CF7F  1               ; SEC is not issued here. Carry from the preceding operations is intentionally
00CF7F  1               ; used by the original code.
00CF7F  1               ; ----------------------------------------------------------------------------
00CF7F  1               
00CF7F  1  E9 1C            sbc #$1C                    ; $CF7F: E9 1C
00CF81  1  0A               asl                         ; $CF81: 0A
00CF82  1  9D 02 03         sta $0302,x                 ; $CF82: 9D 02 03
00CF85  1               
00CF85  1               ; ----------------------------------------------------------------------------
00CF85  1               ; Calculate the fourth byte from the shifted result plus one.
00CF85  1               ; ----------------------------------------------------------------------------
00CF85  1               
00CF85  1  69 01            adc #$01                    ; $CF85: 69 01
00CF87  1  9D 03 03         sta $0303,x                 ; $CF87: 9D 03 03
00CF8A  1               
00CF8A  1  60               rts                         ; $CF8A: 60
00CF8B  1               
00CF8B  1               ; ============================================================================
00CF8B  1               ; $CF8B-$CFA5
00CF8B  1               ; Build a two-byte PPU queue entry using values selected by $34 and $35.
00CF8B  1               ;
00CF8B  1               ; The routine at $EA3E creates a two-byte queue record. The two data bytes are
00CF8B  1               ; read from the lookup table at $C024 using $34 and $35 as indices.
00CF8B  1               ; ============================================================================
00CF8B  1               
00CF8B  1               ; ----------------------------------------------------------------------------
00CF8B  1               ; Contract:
00CF8B  1               ;   Description: Queues Player Value Display.
00CF8B  1               ;   Entry: Registers: A; Memory: playeroneselection, $c024, playertwoselection
00CF8B  1               ;   Returns/products: Registers/clobbers: A, X, Y
00CF8B  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00CF8B  1               ;   Memory effects: $0300, $0301
00CF8B  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00CF8B  1               ;          comparison, load, or store path and are not a stable API product.
00CF8B  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00CF8B  1               ; ----------------------------------------------------------------------------
00CF8B  1               QueuePlayerValueDisplay:                   ; $CF8B
00CF8B  1  A9 2A            lda #$2A                    ; $CF8B: A9 2A
00CF8D  1  A2 A2            ldx #$A2                    ; $CF8D: A2 A2
00CF8F  1  A0 02            ldy #$02                    ; $CF8F: A0 02
00CF91  1               
00CF91  1  38               sec                         ; $CF91: 38
00CF92  1  20 3E EA         jsr AllocateDisplayBufferRecord                   ; $CF92: 20 3E EA
00CF95  1               
00CF95  1               ; ----------------------------------------------------------------------------
00CF95  1               ; Select the first byte using $34.
00CF95  1               ; ----------------------------------------------------------------------------
00CF95  1               
00CF95  1  A4 34            ldy PlayerOneSelection          ; $CF95: A4 34
00CF97  1               
00CF97  1  B9 24 C0         lda $C024,y                 ; $CF97: B9 24 C0
00CF9A  1  9D 00 03         sta $0300,x                 ; $CF9A: 9D 00 03
00CF9D  1               
00CF9D  1               ; ----------------------------------------------------------------------------
00CF9D  1               ; Select the second byte using $35.
00CF9D  1               ; ----------------------------------------------------------------------------
00CF9D  1               
00CF9D  1  A4 35            ldy PlayerTwoSelection          ; $CF9D: A4 35
00CF9F  1               
00CF9F  1  B9 24 C0         lda $C024,y                 ; $CF9F: B9 24 C0
00CFA2  1  9D 01 03         sta $0301,x                 ; $CFA2: 9D 01 03
00CFA5  1               
00CFA5  1  60               rts                         ; $CFA5: 60
00CFA6  1               
00CFA6  1               ; ============================================================================
00CFA6  1               ; $CFA6-$D01C
00CFA6  1               ; Update one of two counters, update a shared total, and build several PPU
00CFA6  1               ; queue entries representing the resulting values.
00CFA6  1               ; ============================================================================
00CFA6  1               
00CFA6  1               ; ----------------------------------------------------------------------------
00CFA6  1               ; Contract:
00CFA6  1               ;   Description: Updates Counters And Display.
00CFA6  1               ;   Entry: Registers: A, X, Y; Memory: roundstateindex, $67, pendingscoreincrement, inningorsharedscore, playeronescore
00CFA6  1               ;   Returns/products: Registers/clobbers: A, X, Y
00CFA6  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00CFA6  1               ;   Memory effects: $67, inningorsharedscore, $0307, $0301, $0300, $0306
00CFA6  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00CFA6  1               ;          comparison, load, or store path and are not a stable API product.
00CFA6  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 2.
00CFA6  1               ; ----------------------------------------------------------------------------
00CFA6  1               UpdateCountersAndDisplay:                   ; $CFA6
00CFA6  1  A5 33            lda RoundStateIndex            ; $CFA6: A5 33
00CFA8  1  29 01            and #$01                    ; $CFA8: 29 01
00CFAA  1  AA               tax                         ; $CFAA: AA
00CFAB  1                                               ; Select counter $67 or $68.
00CFAB  1               
00CFAB  1               ; ----------------------------------------------------------------------------
00CFAB  1               ; Add $65 to the selected counter, saturating the result at $63.
00CFAB  1               ; ----------------------------------------------------------------------------
00CFAB  1               
00CFAB  1  18               clc                         ; $CFAB: 18
00CFAC  1               
00CFAC  1  B5 67            lda PlayerOneScore,x                   ; $CFAC: B5 67
00CFAE  1  65 65            adc PendingScoreIncrement        ; $CFAE: 65 65
00CFB0  1               
00CFB0  1  C9 64            cmp #$64                    ; $CFB0: C9 64
00CFB2  1  90 02            bcc SaveSaturatedSideCounter
00CFB4  1                                               ; $CFB2: 90 02
00CFB4  1               
00CFB4  1  A9 63            lda #$63                    ; $CFB4: A9 63
00CFB6  1               
00CFB6  1               SaveSaturatedSideCounter:       ; $CFB6
00CFB6  1  95 67            sta PlayerOneScore,x                   ; $CFB6: 95 67
00CFB8  1               
00CFB8  1               ; ----------------------------------------------------------------------------
00CFB8  1               ; Add $65 to the shared value at $66 and reduce it using the conversion helper
00CFB8  1               ; at $D01D.
00CFB8  1               ; ----------------------------------------------------------------------------
00CFB8  1               
00CFB8  1  18               clc                         ; $CFB8: 18
00CFB9  1               
00CFB9  1  A5 66            lda InningOrSharedScore           ; $CFB9: A5 66
00CFBB  1  65 65            adc PendingScoreIncrement        ; $CFBB: 65 65
00CFBD  1               
00CFBD  1  20 1D D0         jsr DivideABy10             ; $CFBD: 20 1D D0
00CFC0  1  85 66            sta InningOrSharedScore           ; $CFC0: 85 66
00CFC2  1               
00CFC2  1               ; ----------------------------------------------------------------------------
00CFC2  1               ; Derive a PPU queue position from the selected side in X.
00CFC2  1               ;
00CFC2  1               ; The ROR sequence incorporates X's bit value into A before adding $94.
00CFC2  1               ; ----------------------------------------------------------------------------
00CFC2  1               
00CFC2  1  B5 67            lda PlayerOneScore,x          ; $CFC2: B5 67
00CFC4  1  48               pha                         ; $CFC4: 48
00CFC5  1               
00CFC5  1  8A               txa                         ; $CFC5: 8A
00CFC6  1  4A               lsr                         ; $CFC6: 4A
00CFC7  1  6A               ror                         ; $CFC7: 6A
00CFC8  1  6A               ror                         ; $CFC8: 6A
00CFC9  1  6A               ror                         ; $CFC9: 6A
00CFCA  1               
00CFCA  1  69 94            adc #$94                    ; $CFCA: 69 94
00CFCC  1  AA               tax                         ; $CFCC: AA
00CFCD  1               
00CFCD  1               ; ----------------------------------------------------------------------------
00CFCD  1               ; Create a two-byte PPU queue entry.
00CFCD  1               ; ----------------------------------------------------------------------------
00CFCD  1               
00CFCD  1  A9 20            lda #$20                    ; $CFCD: A9 20
00CFCF  1  A0 02            ldy #$02                    ; $CFCF: A0 02
00CFD1  1               
00CFD1  1  20 3E EA         jsr AllocateDisplayBufferRecord                   ; $CFD1: 20 3E EA
00CFD4  1               
00CFD4  1               ; ----------------------------------------------------------------------------
00CFD4  1               ; Convert the selected counter into display digits.
00CFD4  1               ;
00CFD4  1               ; Routine $D01D returns:
00CFD4  1               ;   A = remainder/digit-like value
00CFD4  1               ;   Y = quotient-like value
00CFD4  1               ; ----------------------------------------------------------------------------
00CFD4  1               
00CFD4  1  68               pla                         ; $CFD4: 68
00CFD5  1  20 1D D0         jsr DivideABy10            ; $CFD5: 20 1D D0
00CFD8  1               
00CFD8  1  9D 07 03         sta $0307,x                 ; $CFD8: 9D 07 03
00CFDB  1               
00CFDB  1  69 27            adc #$27                    ; $CFDB: 69 27
00CFDD  1  9D 01 03         sta $0301,x                 ; $CFDD: 9D 01 03
00CFE0  1               
00CFE0  1               ; ----------------------------------------------------------------------------
00CFE0  1               ; Build the associated leading digit or blank character.
00CFE0  1               ; ----------------------------------------------------------------------------
00CFE0  1               
00CFE0  1  98               tya                         ; $CFE0: 98
00CFE1  1  F0 04            beq BlankLeadingCounterDigit
00CFE3  1                                               ; $CFE1: F0 04
00CFE3  1               
00CFE3  1  69 28            adc #$28                    ; $CFE3: 69 28
00CFE5  1  D0 04            bne StoreCounterDisplayDigits ; $CFE5: D0 04
00CFE7  1                                               ; Always taken for the expected input range.
00CFE7  1               
00CFE7  1               BlankLeadingCounterDigit:      ; $CFE7
00CFE7  1  A0 25            ldy #$25                    ; $CFE7: A0 25
00CFE9  1                                               ; Encoded blank character.
00CFE9  1               
00CFE9  1  A9 33            lda #$33                    ; $CFE9: A9 33
00CFEB  1               
00CFEB  1               StoreCounterDisplayDigits:        ; $CFEB
00CFEB  1  9D 00 03         sta $0300,x                 ; $CFEB: 9D 00 03
00CFEE  1               
00CFEE  1  98               tya                         ; $CFEE: 98
00CFEF  1  9D 06 03         sta $0306,x                 ; $CFEF: 9D 06 03
00CFF2  1               
00CFF2  1               ; ----------------------------------------------------------------------------
00CFF2  1               ; Build a second two-byte queue entry selected by the low bit of $33.
00CFF2  1               ; ----------------------------------------------------------------------------
00CFF2  1               
00CFF2  1  A5 33            lda RoundStateIndex            ; $CFF2: A5 33
00CFF4  1  4A               lsr                         ; $CFF4: 4A
00CFF5  1               
00CFF5  1  A9 A4            lda #$A4                    ; $CFF5: A9 A4
00CFF7  1  90 02            bcc SelectPlayerDisplayQueueOffset   ; $CFF7: 90 02
00CFF9  1               
00CFF9  1  69 1F            adc #$1F                    ; $CFF9: 69 1F
00CFFB  1               
00CFFB  1               SelectPlayerDisplayQueueOffset:          ; $CFFB
00CFFB  1  AA               tax                         ; $CFFB: AA
00CFFC  1               
00CFFC  1  A9 2A            lda #$2A                    ; $CFFC: A9 2A
00CFFE  1  A0 02            ldy #$02                    ; $CFFE: A0 02
00D000  1  18               clc                         ; $D000: 18
00D001  1               
00D001  1  20 3E EA         jsr AllocateDisplayBufferRecord                   ; $D001: 20 3E EA
00D004  1               
00D004  1               ; ----------------------------------------------------------------------------
00D004  1               ; Build a final one-byte queue entry.
00D004  1               ; ----------------------------------------------------------------------------
00D004  1               
00D004  1  A5 33            lda RoundStateIndex            ; $D004: A5 33
00D006  1  4A               lsr                         ; $D006: 4A
00D007  1  90 02            bcc SelectSharedCounterQueueOffset   ; $D007: 90 02
00D009  1               
00D009  1  69 1F            adc #$1F                    ; $D009: 69 1F
00D00B  1               
00D00B  1               SelectSharedCounterQueueOffset:          ; $D00B
00D00B  1  69 8B            adc #$8B                    ; $D00B: 69 8B
00D00D  1  AA               tax                         ; $D00D: AA
00D00E  1               
00D00E  1  A9 20            lda #$20                    ; $D00E: A9 20
00D010  1  A0 01            ldy #$01                    ; $D010: A0 01
00D012  1               
00D012  1  20 3E EA         jsr AllocateDisplayBufferRecord                   ; $D012: 20 3E EA
00D015  1               
00D015  1  A5 66            lda InningOrSharedScore           ; $D015: A5 66
00D017  1  69 28            adc #$28                    ; $D017: 69 28
00D019  1  9D 00 03         sta $0300,x                 ; $D019: 9D 00 03
00D01C  1               
00D01C  1  60               rts                         ; $D01C: 60
00D01D  1               
00D01D  1               ; ============================================================================
00D01D  1               ; $D01D-$D027
00D01D  1               ; Divide an unsigned 8-bit value by ten.
00D01D  1               ;
00D01D  1               ; Entry:
00D01D  1               ;   A = unsigned value to divide
00D01D  1               ;
00D01D  1               ; Exit:
00D01D  1               ;   A = remainder, range $00-$09
00D01D  1               ;   Y = quotient
00D01D  1               ;
00D01D  1               ; The routine repeatedly subtracts ten until the subtraction underflows,
00D01D  1               ; then adds ten back to restore the nonnegative remainder.
00D01D  1               ; ============================================================================
00D01D  1               
00D01D  1               ; ----------------------------------------------------------------------------
00D01D  1               ; Contract:
00D01D  1               ;   Description: Implements Divide A By 1 0.
00D01D  1               ;   Entry: Registers: A, Y
00D01D  1               ;   Returns/products: Registers/clobbers: A, Y; Flags: condition flags may carry result state
00D01D  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00D01D  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00D01D  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00D01D  1               ;          comparison, load, or store path and are not a stable API product.
00D01D  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 4.
00D01D  1               ; ----------------------------------------------------------------------------
00D01D  1               DivideABy10:                   ; $D01D
00D01D  1  A0 FF            ldy #$FF                    ; $D01D: A0 FF
00D01F  1                                               ; The first INY changes this to zero.
00D01F  1               
00D01F  1               Routine_D01F_SubtractTen:       ; $D01F
00D01F  1  38               sec                         ; $D01F: 38
00D020  1  E9 0A            sbc #$0A                    ; $D020: E9 0A
00D022  1               
00D022  1  C8               iny                         ; $D022: C8
00D023  1  B0 FA            bcs Routine_D01F_SubtractTen
00D025  1                                               ; $D023: B0 FA
00D025  1               
00D025  1  69 0A            adc #$0A                    ; $D025: 69 0A
00D027  1                                               ; Carry is clear after the failed subtraction,
00D027  1                                               ; so this restores the remainder without an
00D027  1                                               ; extra increment.
00D027  1               
00D027  1  60               rts                         ; $D027: 60
00D028  1               
00D028  1               ; ============================================================================
00D028  1               ; $D028-$D068
00D028  1               ; Display and format the value at $71.
00D028  1               ; ============================================================================
00D028  1               
00D028  1               DisplaySharedCounter:                   ; $D028
00D028  1  18               clc                         ; $D028: 18
00D029  1               
00D029  1  A9 2A            lda #$2A                    ; $D029: A9 2A
00D02B  1  A2 2D            ldx #$2D                    ; $D02B: A2 2D
00D02D  1  A0 05            ldy #$05                    ; $D02D: A0 05
00D02F  1               
00D02F  1  20 17 EA         jsr CopyInlineDisplayRecord                   ; $D02F: 20 17 EA
00D032  1               
00D032  1  05               .byte $05                   ; $D032
00D033  1  25 25 25 39      .byte $25,$25,$25,$39,$3A   ; $D033-$D037
00D037  1  3A           
00D038  1               
00D038  1  A5 71            lda DisplayCounterValue            ; $D038: A5 71
00D03A  1  C9 64            cmp #$64                    ; $D03A: C9 64
00D03C  1  90 09            bcc ConvertSharedCounterToDigits ; $D03C: 90 09
00D03E  1               
00D03E  1  A9 01            lda #$01                    ; $D03E: A9 01
00D040  1  9D FB 02         sta $02FB,x                 ; $D040: 9D FB 02
00D043  1               
00D043  1  A5 71            lda DisplayCounterValue            ; $D043: A5 71
00D045  1  E9 64            sbc #$64                    ; $D045: E9 64
00D047  1               
00D047  1               ConvertSharedCounterToDigits:        ; $D047
00D047  1  20 1D D0         jsr DivideABy10            ; $D047: 20 1D D0
00D04A  1               
00D04A  1  9D FD 02         sta $02FD,x                 ; $D04A: 9D FD 02
00D04D  1               
00D04D  1  98               tya                         ; $D04D: 98
00D04E  1  9D FC 02         sta $02FC,x                 ; $D04E: 9D FC 02
00D051  1               
00D051  1  A9 5A            lda #$5A                    ; $D051: A9 5A
00D053  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $D053: 20 41 EB
00D056  1               
00D056  1  18               clc                         ; $D056: 18
00D057  1               
00D057  1  A9 2A            lda #$2A                    ; $D057: A9 2A
00D059  1  A2 2D            ldx #$2D                    ; $D059: A2 2D
00D05B  1  A0 05            ldy #$05                    ; $D05B: A0 05
00D05D  1               
00D05D  1  20 17 EA         jsr CopyInlineDisplayRecord                   ; $D05D: 20 17 EA
00D060  1               
00D060  1  05               .byte $05                   ; $D060
00D061  1  26 26 26 26      .byte $26,$26,$26,$26,$26   ; $D061-$D065
00D065  1  26           
00D066  1               
00D066  1  4C 6A EB         jmp CommonEngineExit                   ; $D066: 4C 6A EB
00D069  1               
00D069  1               ; ============================================================================
00D069  1               ; $D069-$D09F
00D069  1               ; Initialize object position and sprite fields from the structured table at
00D069  1               ; $D0A0.
00D069  1               ;
00D069  1               ; Two entry points exist:
00D069  1               ;
00D069  1               ;   $D069 initializes A to $23 before using it as the initial table offset.
00D069  1               ;   $D06B uses the caller-supplied A value as the initial table offset.
00D069  1               ;
00D069  1               ; Table records are seven bytes long. A zero byte in ObjectInitializationTable,Y terminates
00D069  1               ; the record list.
00D069  1               ; ============================================================================
00D069  1               
00D069  1               ; ----------------------------------------------------------------------------
00D069  1               ; Contract:
00D069  1               ;   Description: Initializes Default Objects.
00D069  1               ;   Entry: Registers: A, X, Y; Memory: objectinitializationtable, objectinitxlowfield, objectinitxhighfield, objectinitylowfield, objectinityhighfield, objectinitframefield, objectinitattributefield
00D069  1               ;   Returns/products: Registers/clobbers: A, X, Y
00D069  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00D069  1               ;   Memory effects: $0509, $050a, $053a, $053b, $039b, $03b0
00D069  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00D069  1               ;          comparison, load, or store path and are not a stable API product.
00D069  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00D069  1               ; ----------------------------------------------------------------------------
00D069  1               InitializeDefaultObjects:                   ; $D069
00D069  1  A9 23            lda #$23                    ; $D069: A9 23
00D06B  1               
00D06B  1               ; ----------------------------------------------------------------------------
00D06B  1               ; Secondary entry point.
00D06B  1               ;
00D06B  1               ; Entry:
00D06B  1               ;   A = initial offset into ObjectInitializationTable
00D06B  1               ; ----------------------------------------------------------------------------
00D06B  1               
00D06B  1               ; ----------------------------------------------------------------------------
00D06B  1               ; Contract:
00D06B  1               ;   Description: Initializes Objects From Table.
00D06B  1               ;   Entry: Registers: A, X, Y; Memory: objectinitializationtable, objectinitxlowfield, objectinitxhighfield, objectinitylowfield, objectinityhighfield, objectinitframefield, objectinitattributefield
00D06B  1               ;   Returns/products: Registers/clobbers: A, X, Y
00D06B  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00D06B  1               ;   Memory effects: $0509, $050a, $053a, $053b, $039b, $03b0
00D06B  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00D06B  1               ;          comparison, load, or store path and are not a stable API product.
00D06B  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 2.
00D06B  1               ; ----------------------------------------------------------------------------
00D06B  1               InitializeObjectsFromTable:                   ; $D06B
00D06B  1  A8               tay                         ; $D06B: A8
00D06C  1               
00D06C  1               InitializeNextObjectRecord:        ; $D06C
00D06C  1  BE A0 D0         ldx ObjectInitializationTable,y            ; $D06C: BE A0 D0
00D06F  1  F0 2E            beq ObjectInitializationReturn     ; $D06F: F0 2E
00D071  1               
00D071  1               ; ----------------------------------------------------------------------------
00D071  1               ; Copy four position bytes from the table into the object arrays selected by X.
00D071  1               ; ----------------------------------------------------------------------------
00D071  1               
00D071  1  B9 A3 D0         lda ObjectInitXLowField,y            ; $D071: B9 A3 D0
00D074  1  9D 09 05         sta $0509,x                 ; $D074: 9D 09 05
00D077  1               
00D077  1  B9 A4 D0         lda ObjectInitXHighField,y            ; $D077: B9 A4 D0
00D07A  1  9D 0A 05         sta $050A,x                 ; $D07A: 9D 0A 05
00D07D  1               
00D07D  1  B9 A5 D0         lda ObjectInitYLowField,y            ; $D07D: B9 A5 D0
00D080  1  9D 3A 05         sta $053A,x                 ; $D080: 9D 3A 05
00D083  1               
00D083  1  B9 A6 D0         lda ObjectInitYHighField,y            ; $D083: B9 A6 D0
00D086  1  9D 3B 05         sta $053B,x                 ; $D086: 9D 3B 05
00D089  1               
00D089  1               ; ----------------------------------------------------------------------------
00D089  1               ; Convert the object-array offset into the associated sprite-array index.
00D089  1               ; ----------------------------------------------------------------------------
00D089  1               
00D089  1  8A               txa                         ; $D089: 8A
00D08A  1  4A               lsr                         ; $D08A: 4A
00D08B  1  AA               tax                         ; $D08B: AA
00D08C  1               
00D08C  1               ; ----------------------------------------------------------------------------
00D08C  1               ; Copy the sprite tile/frame value.
00D08C  1               ; ----------------------------------------------------------------------------
00D08C  1               
00D08C  1  B9 A1 D0         lda ObjectInitFrameField,y            ; $D08C: B9 A1 D0
00D08F  1  9D 9B 03         sta $039B,x                 ; $D08F: 9D 9B 03
00D092  1               
00D092  1               ; ----------------------------------------------------------------------------
00D092  1               ; Copy the optional sprite attribute/value when it is nonzero.
00D092  1               ; ----------------------------------------------------------------------------
00D092  1               
00D092  1  B9 A2 D0         lda ObjectInitAttributeField,y            ; $D092: B9 A2 D0
00D095  1  F0 03            beq AdvanceObjectInitRecord ; $D095: F0 03
00D097  1               
00D097  1  9D B0 03         sta $03B0,x                 ; $D097: 9D B0 03
00D09A  1               
00D09A  1               ; ----------------------------------------------------------------------------
00D09A  1               ; Advance to the next seven-byte record.
00D09A  1               ;
00D09A  1               ; Carry is expected to be clear after the table and store operations.
00D09A  1               ; ----------------------------------------------------------------------------
00D09A  1               
00D09A  1               AdvanceObjectInitRecord:        ; $D09A
00D09A  1  98               tya                         ; $D09A: 98
00D09B  1  69 07            adc #$07                    ; $D09B: 69 07
00D09D  1  D0 CC            bne InitializeObjectsFromTable            ; $D09D: D0 CC
00D09F  1                                               ; Effectively loops until a terminating record.
00D09F  1               
00D09F  1               ObjectInitializationReturn:            ; $D09F
00D09F  1  60               rts                         ; $D09F: 60
00D0A0  1               
00D0A0  1               ; ============================================================================
00D0A0  1               ; Structured seven-byte object table begins at CPU $D0A0.
00D0A0  1               ;
00D0A0  1               ; Record format inferred during the first pass:
00D0A0  1               ;
00D0A0  1               ;   +0  object-array offset
00D0A0  1               ;   +1  sprite tile/frame
00D0A0  1               ;   +2  optional sprite attribute/value
00D0A0  1               ;   +3  $0509,X
00D0A0  1               ;   +4  $050A,X
00D0A0  1               ;   +5  $053A,X
00D0A0  1               ;   +6  $053B,X
00D0A0  1               ; ============================================================================
00D0A0  1               
00D0A0  1               ; ============================================================================
00D0A0  1               ; $D0A0-$D125
00D0A0  1               ; Object initialization table used by InitializeDefaultObjects/InitializeObjectsFromTable.
00D0A0  1               ;
00D0A0  1               ; Each record is seven bytes:
00D0A0  1               ;
00D0A0  1               ;   +0  object-array offset in X
00D0A0  1               ;   +1  value stored at $039B,(X / 2)
00D0A0  1               ;   +2  optional value stored at $03B0,(X / 2)
00D0A0  1               ;   +3  value stored at $0509,X
00D0A0  1               ;   +4  value stored at $050A,X
00D0A0  1               ;   +5  value stored at $053A,X
00D0A0  1               ;   +6  value stored at $053B,X
00D0A0  1               ;
00D0A0  1               ; A zero object-array offset terminates the table.
00D0A0  1               ; ============================================================================
00D0A0  1               
00D0A0  1               ObjectInitializationTable:
00D0A0  1               
00D0A0  1               ; ----------------------------------------------------------------------------
00D0A0  1               ; Record 0
00D0A0  1               ;
00D0A0  1               ; Object offset: $06
00D0A0  1               ; Sprite index:  $03
00D0A0  1               ; ----------------------------------------------------------------------------
00D0A0  1               
00D0A0  1               ObjectInit_D0A0:                ; $D0A0
00D0A0  1  06               .byte $06                   ; Object-array offset
00D0A1  1  7A               .byte $7A                   ; $039B + (X / 2)
00D0A2  1  7A               .byte $7A                   ; $03B0 + (X / 2)
00D0A3  1  CD FE            .byte $CD,$FE               ; $0509/$050A
00D0A5  1  4C F8            .byte $4C,$F8               ; $053A/$053B
00D0A7  1               
00D0A7  1               ; ----------------------------------------------------------------------------
00D0A7  1               ; Record 1
00D0A7  1               ; ----------------------------------------------------------------------------
00D0A7  1               
00D0A7  1               ObjectInit_D0A7:                ; $D0A7
00D0A7  1  08               .byte $08
00D0A8  1  7A               .byte $7A
00D0A9  1  7A               .byte $7A
00D0AA  1  00 FC            .byte $00,$FC
00D0AC  1  00 F7            .byte $00,$F7
00D0AE  1               
00D0AE  1               ; ----------------------------------------------------------------------------
00D0AE  1               ; Record 2
00D0AE  1               ; ----------------------------------------------------------------------------
00D0AE  1               
00D0AE  1               ObjectInit_D0AE:                ; $D0AE
00D0AE  1  0A               .byte $0A
00D0AF  1  7A               .byte $7A
00D0B0  1  7A               .byte $7A
00D0B1  1  00 FB            .byte $00,$FB
00D0B3  1  00 F7            .byte $00,$F7
00D0B5  1               
00D0B5  1               ; ----------------------------------------------------------------------------
00D0B5  1               ; Record 3
00D0B5  1               ; ----------------------------------------------------------------------------
00D0B5  1               
00D0B5  1               ObjectInit_D0B5:                ; $D0B5
00D0B5  1  0C               .byte $0C
00D0B6  1  7A               .byte $7A
00D0B7  1  7A               .byte $7A
00D0B8  1  00 FA            .byte $00,$FA
00D0BA  1  00 F7            .byte $00,$F7
00D0BC  1               
00D0BC  1               ; ----------------------------------------------------------------------------
00D0BC  1               ; Record 4
00D0BC  1               ; ----------------------------------------------------------------------------
00D0BC  1               
00D0BC  1               ObjectInit_D0BC:                ; $D0BC
00D0BC  1  02               .byte $02
00D0BD  1  6E               .byte $6E
00D0BE  1  47               .byte $47
00D0BF  1  00 00            .byte $00,$00
00D0C1  1  C0 F6            .byte $C0,$F6
00D0C3  1               
00D0C3  1               ; ----------------------------------------------------------------------------
00D0C3  1               ; Record 5
00D0C3  1               ; ----------------------------------------------------------------------------
00D0C3  1               
00D0C3  1               ObjectInit_D0C3:                ; $D0C3
00D0C3  1  04               .byte $04
00D0C4  1  59               .byte $59
00D0C5  1  11               .byte $11
00D0C6  1  00 00            .byte $00,$00
00D0C8  1  22 F7            .byte $22,$F7
00D0CA  1               
00D0CA  1               ; ----------------------------------------------------------------------------
00D0CA  1               ; Record 6
00D0CA  1               ; ----------------------------------------------------------------------------
00D0CA  1               
00D0CA  1               ObjectInit_D0CA:                ; $D0CA
00D0CA  1  0E               .byte $0E
00D0CB  1  5B               .byte $5B
00D0CC  1  08               .byte $08
00D0CD  1  00 00            .byte $00,$00
00D0CF  1  48 02            .byte $48,$02
00D0D1  1               
00D0D1  1               ; ----------------------------------------------------------------------------
00D0D1  1               ; Record 7
00D0D1  1               ; ----------------------------------------------------------------------------
00D0D1  1               
00D0D1  1               ObjectInit_D0D1:                ; $D0D1
00D0D1  1  10               .byte $10
00D0D2  1  5B               .byte $5B
00D0D3  1  2F               .byte $2F
00D0D4  1  00 08            .byte $00,$08
00D0D6  1  00 05            .byte $00,$05
00D0D8  1               
00D0D8  1               ; ----------------------------------------------------------------------------
00D0D8  1               ; Record 8
00D0D8  1               ; ----------------------------------------------------------------------------
00D0D8  1               
00D0D8  1               ObjectInit_D0D8:                ; $D0D8
00D0D8  1  12               .byte $12
00D0D9  1  5B               .byte $5B
00D0DA  1  2F               .byte $2F
00D0DB  1  00 04            .byte $00,$04
00D0DD  1  00 09            .byte $00,$09
00D0DF  1               
00D0DF  1               ; ----------------------------------------------------------------------------
00D0DF  1               ; Record 9
00D0DF  1               ; ----------------------------------------------------------------------------
00D0DF  1               
00D0DF  1               ObjectInit_D0DF:                ; $D0DF
00D0DF  1  14               .byte $14
00D0E0  1  5B               .byte $5B
00D0E1  1  2F               .byte $2F
00D0E2  1  00 FC            .byte $00,$FC
00D0E4  1  00 09            .byte $00,$09
00D0E6  1               
00D0E6  1               ; ----------------------------------------------------------------------------
00D0E6  1               ; Record 10
00D0E6  1               ; ----------------------------------------------------------------------------
00D0E6  1               
00D0E6  1               ObjectInit_D0E6:                ; $D0E6
00D0E6  1  16               .byte $16
00D0E7  1  5B               .byte $5B
00D0E8  1  2F               .byte $2F
00D0E9  1  00 F8            .byte $00,$F8
00D0EB  1  00 05            .byte $00,$05
00D0ED  1               
00D0ED  1               ; ----------------------------------------------------------------------------
00D0ED  1               ; Record 11
00D0ED  1               ; ----------------------------------------------------------------------------
00D0ED  1               
00D0ED  1               ObjectInit_D0ED:                ; $D0ED
00D0ED  1  18               .byte $18
00D0EE  1  69               .byte $69
00D0EF  1  00               .byte $00                   ; Optional $03B0 value is not written
00D0F0  1  00 0B            .byte $00,$0B
00D0F2  1  00 01            .byte $00,$01
00D0F4  1               
00D0F4  1               ; ----------------------------------------------------------------------------
00D0F4  1               ; Record 12
00D0F4  1               ; ----------------------------------------------------------------------------
00D0F4  1               
00D0F4  1               ObjectInit_D0F4:                ; $D0F4
00D0F4  1  1A               .byte $1A
00D0F5  1  69               .byte $69
00D0F6  1  00               .byte $00
00D0F7  1  00 01            .byte $00,$01
00D0F9  1  00 0A            .byte $00,$0A
00D0FB  1               
00D0FB  1               ; ----------------------------------------------------------------------------
00D0FB  1               ; Record 13
00D0FB  1               ; ----------------------------------------------------------------------------
00D0FB  1               
00D0FB  1               ObjectInit_D0FB:                ; $D0FB
00D0FB  1  1C               .byte $1C
00D0FC  1  69               .byte $69
00D0FD  1  00               .byte $00
00D0FE  1  00 F5            .byte $00,$F5
00D100  1  00 01            .byte $00,$01
00D102  1               
00D102  1               ; ----------------------------------------------------------------------------
00D102  1               ; Record 14
00D102  1               ; ----------------------------------------------------------------------------
00D102  1               
00D102  1               ObjectInit_D102:                ; $D102
00D102  1  1E               .byte $1E
00D103  1  67               .byte $67
00D104  1  00               .byte $00
00D105  1  00 0C            .byte $00,$0C
00D107  1  00 12            .byte $00,$12
00D109  1               
00D109  1               ; ----------------------------------------------------------------------------
00D109  1               ; Record 15
00D109  1               ; ----------------------------------------------------------------------------
00D109  1               
00D109  1               ObjectInit_D109:                ; $D109
00D109  1  20               .byte $20
00D10A  1  67               .byte $67
00D10B  1  00               .byte $00
00D10C  1  00 00            .byte $00,$00
00D10E  1  00 17            .byte $00,$17
00D110  1               
00D110  1               ; ----------------------------------------------------------------------------
00D110  1               ; Record 16
00D110  1               ; ----------------------------------------------------------------------------
00D110  1               
00D110  1               ObjectInit_D110:                ; $D110
00D110  1  22               .byte $22
00D111  1  67               .byte $67
00D112  1  00               .byte $00
00D113  1  00 F4            .byte $00,$F4
00D115  1  00 12            .byte $00,$12
00D117  1               
00D117  1               ; ----------------------------------------------------------------------------
00D117  1               ; Record 17
00D117  1               ; ----------------------------------------------------------------------------
00D117  1               
00D117  1               ObjectInit_D117:                ; $D117
00D117  1  24               .byte $24
00D118  1  69               .byte $69
00D119  1  00               .byte $00
00D11A  1  00 13            .byte $00,$13
00D11C  1  00 0B            .byte $00,$0B
00D11E  1               
00D11E  1               ; ----------------------------------------------------------------------------
00D11E  1               ; Record 18
00D11E  1               ; ----------------------------------------------------------------------------
00D11E  1               
00D11E  1               ObjectInit_D11E:                ; $D11E
00D11E  1  26               .byte $26
00D11F  1  69               .byte $69
00D120  1  00               .byte $00
00D121  1  00 ED            .byte $00,$ED
00D123  1  00 0B            .byte $00,$0B
00D125  1               
00D125  1               ; ----------------------------------------------------------------------------
00D125  1               ; Table terminator
00D125  1               ; ----------------------------------------------------------------------------
00D125  1               
00D125  1               ObjectInitTable_End:            ; $D125
00D125  1  00               .byte $00
00D126  1               
00D126  1               ; ============================================================================
00D126  1               ; Field aliases used by the table-reading routine.
00D126  1               ;
00D126  1               ; These labels correspond to fields in the first record. Indexed accesses use
00D126  1               ; Y as the record offset, so the same labels describe every seven-byte record.
00D126  1               ; ============================================================================
00D126  1               
00D126  1               ObjectInitFrameField = ObjectInitializationTable + 1
00D126  1               ObjectInitAttributeField = ObjectInitializationTable + 2
00D126  1               ObjectInitXLowField = ObjectInitializationTable + 3
00D126  1               ObjectInitXHighField = ObjectInitializationTable + 4
00D126  1               ObjectInitYLowField = ObjectInitializationTable + 5
00D126  1               ObjectInitYHighField = ObjectInitializationTable + 6
00D126  1               
00D126  1               ; ============================================================================
00D126  1               ; $D126-$D14A
00D126  1               ; Conditionally initialize object fields and an animation value.
00D126  1               ;
00D126  1               ; The routine checks the signed state bytes at $0599 and $059A. Processing
00D126  1               ; continues only when:
00D126  1               ;
00D126  1               ;   $0599 is nonnegative
00D126  1               ;   $059A is negative
00D126  1               ;
00D126  1               ; Otherwise, the routine returns immediately.
00D126  1               ; ============================================================================
00D126  1               
00D126  1               ; ----------------------------------------------------------------------------
00D126  1               ; Contract:
00D126  1               ;   Description: Initializes Conditional Object.
00D126  1               ;   Entry: Registers: A, X; Memory: $0599, $059a
00D126  1               ;   Returns/products: Registers/clobbers: A, X
00D126  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00D126  1               ;   Memory effects: objectselectionlowerbound, $03b8
00D126  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00D126  1               ;          comparison, load, or store path and are not a stable API product.
00D126  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00D126  1               ; ----------------------------------------------------------------------------
00D126  1               InitializeConditionalObject:                   ; $D126
00D126  1  A9 00            lda #$00                    ; $D126: A9 00
00D128  1  85 A5            sta ObjectSelectionLowerBound         ; $D128: 85 A5
00D12A  1               
00D12A  1               ; ----------------------------------------------------------------------------
00D12A  1               ; Return if $0599 is negative.
00D12A  1               ; ----------------------------------------------------------------------------
00D12A  1               
00D12A  1  AD 99 05         lda $0599                   ; $D12A: AD 99 05
00D12D  1  30 1B            bmi ConditionalObjectInitReturn     ; $D12D: 30 1B
00D12F  1               
00D12F  1               ; ----------------------------------------------------------------------------
00D12F  1               ; Return if $059A is nonnegative.
00D12F  1               ; ----------------------------------------------------------------------------
00D12F  1               
00D12F  1  AD 9A 05         lda $059A                   ; $D12F: AD 9A 05
00D132  1  10 16            bpl ConditionalObjectInitReturn     ; $D132: 10 16
00D134  1               
00D134  1               ; ----------------------------------------------------------------------------
00D134  1               ; Initialize indexed object fields.
00D134  1               ;
00D134  1               ; Routine $C9A7 consumes the five bytes immediately following the JSR:
00D134  1               ;
00D134  1               ;   $10                 inline metadata/object offset
00D134  1               ;   $00,$07,$00,$00     four field values
00D134  1               ;
00D134  1               ; Based on Routine_C9A7, the four field bytes are stored into:
00D134  1               ;
00D134  1               ;   $0509,X = $00
00D134  1               ;   $050A,X = $07
00D134  1               ;   $053A,X = $00
00D134  1               ;   $053B,X = $00
00D134  1               ; ============================================================================
00D134  1               
00D134  1  20 A7 C9         jsr LoadObjectPositionInline
00D137  1                                               ; $D134: 20 A7 C9
00D137  1               
00D137  1  10               .byte $10                   ; $D137: inline metadata/object offset
00D138  1  00 07 00 00      .byte $00,$07,$00,$00       ; $D138-$D13B: field data
00D13C  1               
00D13C  1               ; ----------------------------------------------------------------------------
00D13C  1               ; Set the working value at $A5, then run the indexed helper at $E6B7.
00D13C  1               ; ----------------------------------------------------------------------------
00D13C  1               
00D13C  1  A2 10            ldx #$10                    ; $D13C: A2 10
00D13E  1  86 A5            stx ObjectSelectionLowerBound         ; $D13E: 86 A5
00D140  1               
00D140  1  20 B7 E6         jsr ClearMovementTransforms                   ; $D140: 20 B7 E6
00D143  1  B0 05            bcs ConditionalObjectInitReturn     ; $D143: B0 05
00D145  1               
00D145  1               ; ----------------------------------------------------------------------------
00D145  1               ; On success, set the animation/state value at $03B8 to $2A.
00D145  1               ; ----------------------------------------------------------------------------
00D145  1               
00D145  1  A9 2A            lda #$2A                    ; $D145: A9 2A
00D147  1  8D B8 03         sta $03B8                   ; $D147: 8D B8 03
00D14A  1               
00D14A  1               ConditionalObjectInitReturn:            ; $D14A
00D14A  1  60               rts                         ; $D14A: 60
00D14B  1               
00D14B  1               ; ============================================================================
00D14B  1               ; $D14B-$D166
00D14B  1               ; Lookup tables used by the routines beginning around $D167 and $D1D0.
00D14B  1               ;
00D14B  1               ; The exact semantic meanings remain provisional in the first pass, but later
00D14B  1               ; indexed references establish these boundaries:
00D14B  1               ;
00D14B  1               ;   $D14B-$D153  nine-byte lookup table
00D14B  1               ;   $D154-$D15C  nine-byte lookup table
00D14B  1               ;   $D15D-$D161  five-byte lookup table
00D14B  1               ;   $D162-$D166  five-byte lookup table
00D14B  1               ; ============================================================================
00D14B  1               
00D14B  1               ; ----------------------------------------------------------------------------
00D14B  1               ; Nine-byte threshold or selection table.
00D14B  1               ;
00D14B  1               ; Later code searches this table using X values below nine.
00D14B  1               ; ----------------------------------------------------------------------------
00D14B  1               
00D14B  1               PitchDirectionThresholdTable:                     ; $D14B
00D14B  1  00 4E 77 8C      .byte $00,$4E,$77,$8C
00D14F  1  94 A7 D0 E5      .byte $94,$A7,$D0,$E5
00D153  1  ED               .byte $ED
00D154  1               
00D154  1               ; ----------------------------------------------------------------------------
00D154  1               ; Nine-byte result table paired with PitchDirectionThresholdTable.
00D154  1               ;
00D154  1               ; Entries appear to be returned or stored after a matching threshold is found
00D154  1               ; in PitchDirectionThresholdTable.
00D154  1               ; ----------------------------------------------------------------------------
00D154  1               
00D154  1               PitchDirectionResultTable:                     ; $D154
00D154  1  00 05 01 04      .byte $00,$05,$01,$04
00D158  1  06 0A 02 08      .byte $06,$0A,$02,$08
00D15C  1  09               .byte $09
00D15D  1               
00D15D  1               ; ----------------------------------------------------------------------------
00D15D  1               ; Five-byte threshold or selection table.
00D15D  1               ; ----------------------------------------------------------------------------
00D15D  1               
00D15D  1               PitchTypeThresholdTable:                     ; $D15D
00D15D  1  00 1A 80 9A      .byte $00,$1A,$80,$9A,$C0
00D161  1  C0           
00D162  1               
00D162  1               ; ----------------------------------------------------------------------------
00D162  1               ; Five-byte result table paired with PitchTypeThresholdTable.
00D162  1               ; ----------------------------------------------------------------------------
00D162  1               
00D162  1               PitchTypeResultTable:                     ; $D162
00D162  1  00 04 08 00      .byte $00,$04,$08,$00,$04
00D166  1  04           
00D167  1               
00D167  1               ; ============================================================================
00D167  1               ; $D167-$D18A
00D167  1               ; Conditional command dispatch followed by state and object-field
00D167  1               ; initialization.
00D167  1               ; ============================================================================
00D167  1               
00D167  1               InitializePrimaryGameplayActor:                   ; $D167
00D167  1  A5 0F            lda DerivedControl0                     ; $D167: A5 0F
00D169  1  D0 06            bne ClearPrimaryActorState ; $D169: D0 06
00D16B  1               
00D16B  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $D16B: 20 0A EB
00D16E  1               
00D16E  1                   ; Inline command record consumed by QueueInlineObjectEvent.
00D16E  1  19 F7 D3         .byte $19,$F7,$D3           ; $D16E-$D170
00D171  1               
00D171  1               ; ----------------------------------------------------------------------------
00D171  1               ; Clear working state variables.
00D171  1               ; ----------------------------------------------------------------------------
00D171  1               
00D171  1               ClearPrimaryActorState:        ; $D171
00D171  1  A9 00            lda #$00                    ; $D171: A9 00
00D173  1               
00D173  1  85 9D            sta CurrentActionState             ; $D173: 85 9D
00D175  1  85 81            sta RandomValue81           ; $D175: 85 81
00D177  1  85 82            sta ActorActionComplete                 ; $D177: 85 82
00D179  1  85 7F            sta SelectedStateCount      ; $D179: 85 7F
00D17B  1  85 87            sta ObjectProximityState                 ; $D17B: 85 87
00D17D  1               
00D17D  1               ; ----------------------------------------------------------------------------
00D17D  1               ; Initialize the base object fields using the six inline bytes following the
00D17D  1               ; call to LoadBasePositionFieldsInline.
00D17D  1               ;
00D17D  1               ; Routine $C963 stores these bytes as:
00D17D  1               ;
00D17D  1               ;   $0509 = $00
00D17D  1               ;   $050A = $00
00D17D  1               ;   $053A = $46
00D17D  1               ;   $053B = $02
00D17D  1               ;   $056B = $00
00D17D  1               ;   $056C = $02
00D17D  1               ; ----------------------------------------------------------------------------
00D17D  1               
00D17D  1  20 63 C9         jsr LoadBasePositionFieldsInline ; $D17D: 20 63 C9
00D180  1               
00D180  1  00 00            .byte $00,$00               ; $D180-$D181
00D182  1  46 02            .byte $46,$02               ; $D182-$D183
00D184  1  00 02            .byte $00,$02               ; $D184-$D185
00D186  1               
00D186  1               ; ----------------------------------------------------------------------------
00D186  1               ; Initialize the animation/state value at $03B2.
00D186  1               ; ----------------------------------------------------------------------------
00D186  1               
00D186  1  A9 11            lda #$11                    ; $D186: A9 11
00D188  1  8D B2 03         sta $03B2                   ; $D188: 8D B2 03
00D18B  1               
00D18B  1               ; ============================================================================
00D18B  1               ; $D18B-$D1CF
00D18B  1               ; Generate a randomized loop count, animate $03B7, optionally run an extra
00D18B  1               ; timing sequence, and dispatch an inline command.
00D18B  1               ; ============================================================================
00D18B  1               
00D18B  1               RunPitcherWindupSequence:                   ; $D18B
00D18B  1  20 F5 E5         jsr AdvanceRandomState                   ; $D18B: 20 F5 E5
00D18E  1  85 73            sta WindupLoopCounter         ; $D18E: 85 73
00D190  1               
00D190  1               ; ----------------------------------------------------------------------------
00D190  1               ; Transform the random byte into a value whose upper six bits are set.
00D190  1               ;
00D190  1               ; A = ((random >> 2) OR random OR $FC)
00D190  1               ;
00D190  1               ; This produces a short increment loop ending when WindupLoopCounter wraps to zero.
00D190  1               ; ----------------------------------------------------------------------------
00D190  1               
00D190  1  4A               lsr                         ; $D190: 4A
00D191  1  4A               lsr                         ; $D191: 4A
00D192  1               
00D192  1  05 73            ora WindupLoopCounter         ; $D192: 05 73
00D194  1  09 FC            ora #$FC                    ; $D194: 09 FC
00D196  1  85 73            sta WindupLoopCounter         ; $D196: 85 73
00D198  1               
00D198  1  D0 08            bne SetWindupFrame   ; $D198: D0 08
00D19A  1                                               ; Normally taken because OR #$FC makes the
00D19A  1                                               ; result nonzero.
00D19A  1               
00D19A  1               ; ----------------------------------------------------------------------------
00D19A  1               ; Alternate entry when the transformed value is zero.
00D19A  1               ; ----------------------------------------------------------------------------
00D19A  1               
00D19A  1               RunWindupAlternateFrame:    ; $D19A
00D19A  1  CE B7 03         dec $03B7                   ; $D19A: CE B7 03
00D19D  1               
00D19D  1  A9 0F            lda #$0F                    ; $D19D: A9 0F
00D19F  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $D19F: 20 41 EB
00D1A2  1               
00D1A2  1               ; ----------------------------------------------------------------------------
00D1A2  1               ; Set animation/frame $03B7 to seven and wait $3C ticks.
00D1A2  1               ; ----------------------------------------------------------------------------
00D1A2  1               
00D1A2  1               SetWindupFrame:          ; $D1A2
00D1A2  1  A9 07            lda #$07                    ; $D1A2: A9 07
00D1A4  1  8D B7 03         sta $03B7                   ; $D1A4: 8D B7 03
00D1A7  1               
00D1A7  1  A9 3C            lda #$3C                    ; $D1A7: A9 3C
00D1A9  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $D1A9: 20 41 EB
00D1AC  1               
00D1AC  1               ; ----------------------------------------------------------------------------
00D1AC  1               ; Increment $73 until it wraps to zero.
00D1AC  1               ;
00D1AC  1               ; Each nonzero result loops through the frame-decrement and short-delay path
00D1AC  1               ; at $D19A before restoring frame seven and waiting again.
00D1AC  1               ; ----------------------------------------------------------------------------
00D1AC  1               
00D1AC  1  E6 73            inc WindupLoopCounter         ; $D1AC: E6 73
00D1AE  1  D0 EA            bne RunWindupAlternateFrame
00D1B0  1                                               ; $D1AE: D0 EA
00D1B0  1               
00D1B0  1               ; ----------------------------------------------------------------------------
00D1B0  1               ; Advance the animation/frame once after the randomized loop completes.
00D1B0  1               ; ----------------------------------------------------------------------------
00D1B0  1               
00D1B0  1  EE B7 03         inc $03B7                   ; $D1B0: EE B7 03
00D1B3  1               
00D1B3  1               ; ----------------------------------------------------------------------------
00D1B3  1               ; Skip the optional two-step animation when $0599 is negative.
00D1B3  1               ; ----------------------------------------------------------------------------
00D1B3  1               
00D1B3  1  AD 99 05         lda $0599                   ; $D1B3: AD 99 05
00D1B6  1  30 10            bmi FinishWindupSequence ; $D1B6: 30 10
00D1B8  1               
00D1B8  1  A9 1E            lda #$1E                    ; $D1B8: A9 1E
00D1BA  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $D1BA: 20 41 EB
00D1BD  1               
00D1BD  1  EE B7 03         inc $03B7                   ; $D1BD: EE B7 03
00D1C0  1               
00D1C0  1  A9 1E            lda #$1E                    ; $D1C0: A9 1E
00D1C2  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $D1C2: 20 41 EB
00D1C5  1               
00D1C5  1  CE B7 03         dec $03B7                   ; $D1C5: CE B7 03
00D1C8  1               
00D1C8  1               ; ----------------------------------------------------------------------------
00D1C8  1               ; Dispatch the next state through an inline command record.
00D1C8  1               ; ----------------------------------------------------------------------------
00D1C8  1               
00D1C8  1               FinishWindupSequence:        ; $D1C8
00D1C8  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $D1C8: 20 0A EB
00D1CB  1               
00D1CB  1                   ; Inline command record consumed by QueueInlineObjectEvent.
00D1CB  1  17 AC D2         .byte $17,$AC,$D2           ; $D1CB-$D1CD
00D1CE  1               
00D1CE  1  E6 7E            inc ActionSequenceCounter         ; $D1CE: E6 7E
00D1D0  1               
00D1D0  1               ; ============================================================================
00D1D0  1               ; $D1D0-$D2A3
00D1D0  1               ; Randomized decision, animation, movement adjustment, and state transition.
00D1D0  1               ; ============================================================================
00D1D0  1               
00D1D0  1               SelectPitchAction:                   ; $D1D0
00D1D0  1  20 48 EB         jsr SelectObjectEventBank1                   ; $D1D0: 20 48 EB
00D1D3  1               
00D1D3  1  A5 10            lda $10                     ; $D1D3: A5 10
00D1D5  1  D0 33            bne UseControllerPitchSelection
00D1D7  1                                               ; $D1D5: D0 33
00D1D7  1               
00D1D7  1               ; ----------------------------------------------------------------------------
00D1D7  1               ; Wait $3C ticks before making a randomized selection.
00D1D7  1               ; ----------------------------------------------------------------------------
00D1D7  1               
00D1D7  1  A9 3C            lda #$3C                    ; $D1D7: A9 3C
00D1D9  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $D1D9: 20 41 EB
00D1DC  1               
00D1DC  1  20 F5 E5         jsr AdvanceRandomState                   ; $D1DC: 20 F5 E5
00D1DF  1               
00D1DF  1               ; ----------------------------------------------------------------------------
00D1DF  1               ; Search backward through $9F-$A1 for an entry below eight.
00D1DF  1               ;
00D1DF  1               ; X begins at two. The first entry below eight determines X.
00D1DF  1               ; ----------------------------------------------------------------------------
00D1DF  1               
00D1DF  1  A2 02            ldx #$02                    ; $D1DF: A2 02
00D1E1  1               
00D1E1  1               FindAvailablePitchState:       ; $D1E1
00D1E1  1  B4 9F            ldy SecondaryActorState0,x                   ; $D1E1: B4 9F
00D1E3  1               
00D1E3  1  C0 08            cpy #$08                    ; $D1E3: C0 08
00D1E5  1  90 03            bcc SelectPitchType
00D1E7  1                                               ; $D1E5: 90 03
00D1E7  1               
00D1E7  1  CA               dex                         ; $D1E7: CA
00D1E8  1  10 F7            bpl FindAvailablePitchState
00D1EA  1                                               ; $D1E8: 10 F7
00D1EA  1               
00D1EA  1               ; ----------------------------------------------------------------------------
00D1EA  1               ; Rotate the random value, then select from paired tables at $D15D/$D162.
00D1EA  1               ; ----------------------------------------------------------------------------
00D1EA  1               
00D1EA  1               SelectPitchType:  ; $D1EA
00D1EA  1  6A               ror                         ; $D1EA: 6A
00D1EB  1               
00D1EB  1  A2 05            ldx #$05                    ; $D1EB: A2 05
00D1ED  1               
00D1ED  1               SearchPitchTypeThresholds:  ; $D1ED
00D1ED  1  CA               dex                         ; $D1ED: CA
00D1EE  1               
00D1EE  1  DD 5D D1         cmp PitchTypeThresholdTable,x            ; $D1EE: DD 5D D1
00D1F1  1  90 FA            bcc SearchPitchTypeThresholds
00D1F3  1                                               ; $D1F1: 90 FA
00D1F3  1               
00D1F3  1  BD 62 D1         lda PitchTypeResultTable,x            ; $D1F3: BD 62 D1
00D1F6  1  85 21            sta SelectedPitchAction          ; $D1F6: 85 21
00D1F8  1               
00D1F8  1               ; ----------------------------------------------------------------------------
00D1F8  1               ; Make a second randomized table selection using $D14B/$D154.
00D1F8  1               ; ----------------------------------------------------------------------------
00D1F8  1               
00D1F8  1  20 F5 E5         jsr AdvanceRandomState                   ; $D1F8: 20 F5 E5
00D1FB  1               
00D1FB  1  A2 09            ldx #$09                    ; $D1FB: A2 09
00D1FD  1               
00D1FD  1               SearchPitchDirectionThresholds: ; $D1FD
00D1FD  1  CA               dex                         ; $D1FD: CA
00D1FE  1               
00D1FE  1  DD 4B D1         cmp PitchDirectionThresholdTable,x            ; $D1FE: DD 4B D1
00D201  1  90 FA            bcc SearchPitchDirectionThresholds
00D203  1                                               ; $D201: 90 FA
00D203  1               
00D203  1  BD 54 D1         lda PitchDirectionResultTable,x            ; $D203: BD 54 D1
00D206  1  85 91            sta $91                     ; $D206: 85 91
00D208  1               
00D208  1  B0 08            bcs AnimatePitchStart    ; $D208: B0 08
00D20A  1                                               ; Always taken after the table search succeeds.
00D20A  1               
00D20A  1               ; ----------------------------------------------------------------------------
00D20A  1               ; Alternate path used when $10 is nonzero.
00D20A  1               ; ----------------------------------------------------------------------------
00D20A  1               
00D20A  1               UseControllerPitchSelection: ; $D20A
00D20A  1  A5 14            lda InputState2             ; $D20A: A5 14
00D20C  1  85 21            sta SelectedPitchAction          ; $D20C: 85 21
00D20E  1               
00D20E  1  A5 18            lda InputAux2               ; $D20E: A5 18
00D210  1  10 BE            bpl SelectPitchAction            ; $D210: 10 BE
00D212  1               
00D212  1               ; ----------------------------------------------------------------------------
00D212  1               ; Process event slot $17 and dispatch the next state.
00D212  1               ; ----------------------------------------------------------------------------
00D212  1               
00D212  1               AnimatePitchStart:           ; $D212
00D212  1  A0 17            ldy #$17                    ; $D212: A0 17
00D214  1  20 66 EB         jsr DispatchNextQueuedEvent                   ; $D214: 20 66 EB
00D217  1               
00D217  1  20 48 EB         jsr SelectObjectEventBank1                   ; $D217: 20 48 EB
00D21A  1               
00D21A  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $D21A: 20 0A EB
00D21D  1               
00D21D  1                   ; Inline command record consumed by QueueInlineObjectEvent.
00D21D  1  13 DA D6         .byte $13,$DA,$D6           ; $D21D-$D21F
00D220  1               
00D220  1               ; ----------------------------------------------------------------------------
00D220  1               ; Animate $03B7 from $0C through $0F with a ten-tick delay between frames.
00D220  1               ; ----------------------------------------------------------------------------
00D220  1               
00D220  1  A9 0C            lda #$0C                    ; $D220: A9 0C
00D222  1  8D B7 03         sta $03B7                   ; $D222: 8D B7 03
00D225  1               
00D225  1               PitchStartAnimationLoop:     ; $D225
00D225  1  A9 0A            lda #$0A                    ; $D225: A9 0A
00D227  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $D227: 20 41 EB
00D22A  1               
00D22A  1  EE B7 03         inc $03B7                   ; $D22A: EE B7 03
00D22D  1               
00D22D  1  AD B7 03         lda $03B7                   ; $D22D: AD B7 03
00D230  1  C9 0F            cmp #$0F                    ; $D230: C9 0F
00D232  1  90 F1            bcc PitchStartAnimationLoop
00D234  1                                               ; $D232: 90 F1
00D234  1               
00D234  1               ; ----------------------------------------------------------------------------
00D234  1               ; Use bits 2-3 of $21 to select entries from the tables at $D2A4-$D2AC.
00D234  1               ; ----------------------------------------------------------------------------
00D234  1               
00D234  1  A5 21            lda SelectedPitchAction          ; $D234: A5 21
00D236  1  4A               lsr                         ; $D236: 4A
00D237  1  4A               lsr                         ; $D237: 4A
00D238  1               
00D238  1  29 03            and #$03                    ; $D238: 29 03
00D23A  1  AA               tax                         ; $D23A: AA
00D23B  1               
00D23B  1  BD AA D2         lda PitchRenderFlagTable,x            ; $D23B: BD AA D2
00D23E  1  85 FF            sta RenderStateFlags           ; $D23E: 85 FF
00D240  1               
00D240  1               ; ----------------------------------------------------------------------------
00D240  1               ; Combine a random value with the signed table at $D2A4, then use the result as
00D240  1               ; Y to select a delay from the table at $D2A7.
00D240  1               ; ----------------------------------------------------------------------------
00D240  1               
00D240  1  20 F5 E5         jsr AdvanceRandomState                   ; $D240: 20 F5 E5
00D243  1               
00D243  1  09 F0            ora #$F0                    ; $D243: 09 F0
00D245  1  FD A4 D2         sbc PitchVelocityBiasTable,x            ; $D245: FD A4 D2
00D248  1  A8               tay                         ; $D248: A8
00D249  1               
00D249  1  BD A7 D2         lda PitchDelayTable,x            ; $D249: BD A7 D2
00D24C  1  85 94            sta PitchUpdateDelay           ; $D24C: 85 94
00D24E  1               
00D24E  1               ; ----------------------------------------------------------------------------
00D24E  1               ; Initialize base movement state.
00D24E  1               ;
00D24E  1               ; Y from the preceding calculation is passed to InitializeBaseMotionZero.
00D24E  1               ; ----------------------------------------------------------------------------
00D24E  1               
00D24E  1  A2 00            ldx #$00                    ; $D24E: A2 00
00D250  1  20 23 CA         jsr InitializeBaseMotionZero            ; $D250: 20 23 CA
00D253  1               
00D253  1               ; ----------------------------------------------------------------------------
00D253  1               ; Generate and transform another random value through the helper at $C036.
00D253  1               ; The result is stored as both $71 and $81.
00D253  1               ; ----------------------------------------------------------------------------
00D253  1               
00D253  1  20 F5 E5         jsr AdvanceRandomState                   ; $D253: 20 F5 E5
00D256  1  20 36 C0         jsr $C036       ; $D256: 20 36 C0
00D259  1               
00D259  1  85 71            sta DisplayCounterValue            ; $D259: 85 71
00D25B  1  85 81            sta RandomValue81           ; $D25B: 85 81
00D25D  1               
00D25D  1  E6 9D            inc CurrentActionState             ; $D25D: E6 9D
00D25F  1               
00D25F  1               ; ----------------------------------------------------------------------------
00D25F  1               ; Dispatch the next state through an inline command.
00D25F  1               ; ----------------------------------------------------------------------------
00D25F  1               
00D25F  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $D25F: 20 0A EB
00D262  1               
00D262  1                   ; Inline command record consumed by QueueInlineObjectEvent.
00D262  1  04 85 D7         .byte $04,$85,$D7           ; $D262-$D264
00D265  1               
00D265  1               ; ----------------------------------------------------------------------------
00D265  1               ; Wait using the selected delay value from $94.
00D265  1               ; ----------------------------------------------------------------------------
00D265  1               
00D265  1               UpdatePitchMovement:     ; $D265
00D265  1  A5 94            lda PitchUpdateDelay           ; $D265: A5 94
00D267  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $D267: 20 41 EB
00D26A  1               
00D26A  1               ; ----------------------------------------------------------------------------
00D26A  1               ; Choose a direction/control value.
00D26A  1               ; ----------------------------------------------------------------------------
00D26A  1               
00D26A  1  A5 10            lda $10                     ; $D26A: A5 10
00D26C  1  D0 0D            bne UsePitchControllerInput   ; $D26C: D0 0D
00D26E  1               
00D26E  1  A5 91            lda PitchDirectionDecision         ; $D26E: A5 91
00D270  1               
00D270  1  AE 3B 05         ldx $053B                   ; $D270: AE 3B 05
00D273  1  E0 FD            cpx #$FD                    ; $D273: E0 FD
00D275  1  10 06            bpl ApplyPitchHorizontalInput   ; $D275: 10 06
00D277  1               
00D277  1  4A               lsr                         ; $D277: 4A
00D278  1  4A               lsr                         ; $D278: 4A
00D279  1               
00D279  1  D0 02            bne ApplyPitchHorizontalInput   ; $D279: D0 02
00D27B  1               
00D27B  1               UsePitchControllerInput:          ; $D27B
00D27B  1  A5 14            lda InputState2             ; $D27B: A5 14
00D27D  1               
00D27D  1               ; ----------------------------------------------------------------------------
00D27D  1               ; Adjust the signed high movement byte at $0508 according to bits in A.
00D27D  1               ; ----------------------------------------------------------------------------
00D27D  1               
00D27D  1               ApplyPitchHorizontalInput:          ; $D27D
00D27D  1  4A               lsr                         ; $D27D: 4A
00D27E  1  90 05            bcc ApplyPitchLeftInput
00D280  1                                               ; $D27E: 90 05
00D280  1               
00D280  1  EE 08 05         inc $0508                   ; $D280: EE 08 05
00D283  1  B0 06            bcs SetPitchMovementFlags   ; $D283: B0 06
00D285  1                                               ; Always taken because LSR set carry.
00D285  1               
00D285  1               ApplyPitchLeftInput:     ; $D285
00D285  1  4A               lsr                         ; $D285: 4A
00D286  1  90 07            bcc CheckPitchVerticalLimit
00D288  1                                               ; $D286: 90 07
00D288  1               
00D288  1  CE 08 05         dec $0508                   ; $D288: CE 08 05
00D28B  1               
00D28B  1               SetPitchMovementFlags:          ; $D28B
00D28B  1  A9 08            lda #$08                    ; $D28B: A9 08
00D28D  1  85 FF            sta RenderStateFlags           ; $D28D: 85 FF
00D28F  1               
00D28F  1               ; ----------------------------------------------------------------------------
00D28F  1               ; Continue until the vertical high position reaches $FA or greater.
00D28F  1               ; ----------------------------------------------------------------------------
00D28F  1               
00D28F  1               CheckPitchVerticalLimit:       ; $D28F
00D28F  1  AD 3B 05         lda $053B                   ; $D28F: AD 3B 05
00D292  1  C9 FA            cmp #$FA                    ; $D292: C9 FA
00D294  1  10 CF            bpl UpdatePitchMovement
00D296  1                                               ; $D294: 10 CF
00D296  1               
00D296  1               ; ----------------------------------------------------------------------------
00D296  1               ; Set the final animation value, dispatch the next state, and leave.
00D296  1               ; ----------------------------------------------------------------------------
00D296  1               
00D296  1  A9 2F            lda #$2F                    ; $D296: A9 2F
00D298  1  8D B7 03         sta $03B7                   ; $D298: 8D B7 03
00D29B  1               
00D29B  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $D29B: 20 0A EB
00D29E  1               
00D29E  1                   ; Inline command record consumed by QueueInlineObjectEvent.
00D29E  1  21 27 D0         .byte $21,$27,$D0           ; $D29E-$D2A0
00D2A1  1               
00D2A1  1  4C 6A EB         jmp CommonEngineExit                   ; $D2A1: 4C 6A EB
00D2A4  1               
00D2A4  1               ; ============================================================================
00D2A4  1               ; $D2A4-$D2AC
00D2A4  1               ; Three parallel three-byte lookup tables selected by bits 2-3 of $21.
00D2A4  1               ; ============================================================================
00D2A4  1               
00D2A4  1               PitchVelocityBiasTable:                     ; $D2A4
00D2A4  1  37 47 27         .byte $37,$47,$27
00D2A7  1               
00D2A7  1               PitchDelayTable:                     ; $D2A7
00D2A7  1  05 04 06         .byte $05,$04,$06
00D2AA  1               
00D2AA  1               PitchRenderFlagTable:                     ; $D2AA
00D2AA  1  02 01 04         .byte $02,$01,$04
00D2AD  1               
00D2AD  1               ; ============================================================================
00D2AD  1               ; $D2AD-$D329
00D2AD  1               ; Timed selection loop, player/input selection, event processing, and state
00D2AD  1               ; transition.
00D2AD  1               ; ============================================================================
00D2AD  1               
00D2AD  1               SelectBatterAction:                   ; $D2AD
00D2AD  1  A9 30            lda #$30                    ; $D2AD: A9 30
00D2AF  1  8D C8 05         sta $05C8                   ; $D2AF: 8D C8 05
00D2B2  1               
00D2B2  1               ; ----------------------------------------------------------------------------
00D2B2  1               ; Wait for a frame and evaluate the current input/state.
00D2B2  1               ; ----------------------------------------------------------------------------
00D2B2  1               
00D2B2  1               WaitForBatterAction:         ; $D2B2
00D2B2  1  20 48 EB         jsr SelectObjectEventBank1                   ; $D2B2: 20 48 EB
00D2B5  1               
00D2B5  1  A5 10            lda $10                     ; $D2B5: A5 10
00D2B7  1  D0 1B            bne UseBatterControllerInput   ; $D2B7: D0 1B
00D2B9  1               
00D2B9  1  A5 82            lda ActorActionComplete                 ; $D2B9: A5 82
00D2BB  1  D0 F0            bne SelectBatterAction            ; $D2BB: D0 F0
00D2BD  1               
00D2BD  1               ; ----------------------------------------------------------------------------
00D2BD  1               ; Check three entries at $0575, $0573, and $0571.
00D2BD  1               ;
00D2BD  1               ; If any entry is nonzero, control branches forward to $D32A.
00D2BD  1               ; ----------------------------------------------------------------------------
00D2BD  1               
00D2BD  1  A2 04            ldx #$04                    ; $D2BD: A2 04
00D2BF  1               
00D2BF  1               CheckActiveFieldObjects:      ; $D2BF
00D2BF  1  BD 75 05         lda $0575,x                 ; $D2BF: BD 75 05
00D2C2  1  D0 66            bne SelectActionFromObjectState            ; $D2C2: D0 66
00D2C4  1               
00D2C4  1  CA               dex                         ; $D2C4: CA
00D2C5  1  CA               dex                         ; $D2C5: CA
00D2C6  1  10 F7            bpl CheckActiveFieldObjects
00D2C8  1                                               ; $D2C6: 10 F7
00D2C8  1               
00D2C8  1               ; ----------------------------------------------------------------------------
00D2C8  1               ; Count down $05C8 while no active entry is found.
00D2C8  1               ; ----------------------------------------------------------------------------
00D2C8  1               
00D2C8  1  CE C8 05         dec $05C8                   ; $D2C8: CE C8 05
00D2CB  1  D0 E5            bne WaitForBatterAction  ; $D2CB: D0 E5
00D2CD  1               
00D2CD  1               ; ----------------------------------------------------------------------------
00D2CD  1               ; If the random value is below $46, continue at $D2D9.
00D2CD  1               ; Otherwise, use the current input byte at $18.
00D2CD  1               ; ----------------------------------------------------------------------------
00D2CD  1               
00D2CD  1  20 F5 E5         jsr AdvanceRandomState                   ; $D2CD: 20 F5 E5
00D2D0  1  C9 46            cmp #$46                    ; $D2D0: C9 46
00D2D2  1  90 05            bcc SelectBatterActionSlot ; $D2D2: 90 05
00D2D4  1               
00D2D4  1               UseBatterControllerInput:          ; $D2D4
00D2D4  1  A5 18            lda InputAux2               ; $D2D4: A5 18
00D2D6  1  0A               asl                         ; $D2D6: 0A
00D2D7  1  10 D9            bpl WaitForBatterAction  ; $D2D7: 10 D9
00D2D9  1               
00D2D9  1               ; ----------------------------------------------------------------------------
00D2D9  1               ; Search backward through $9F-$A1 for an entry below eight.
00D2D9  1               ; ----------------------------------------------------------------------------
00D2D9  1               
00D2D9  1               SelectBatterActionSlot:        ; $D2D9
00D2D9  1  A2 03            ldx #$03                    ; $D2D9: A2 03
00D2DB  1               
00D2DB  1               FindAvailableBatterActionSlot:        ; $D2DB
00D2DB  1  CA               dex                         ; $D2DB: CA
00D2DC  1  30 CF            bmi SelectBatterAction            ; $D2DC: 30 CF
00D2DE  1               
00D2DE  1  B5 9F            lda SecondaryActorState0,x                   ; $D2DE: B5 9F
00D2E0  1  C9 08            cmp #$08                    ; $D2E0: C9 08
00D2E2  1  B0 F7            bcs FindAvailableBatterActionSlot ; $D2E2: B0 F7
00D2E4  1               
00D2E4  1  E6 7F            inc SelectedStateCount      ; $D2E4: E6 7F
00D2E6  1               
00D2E6  1               ; ----------------------------------------------------------------------------
00D2E6  1               ; Select the working value for $21.
00D2E6  1               ; ----------------------------------------------------------------------------
00D2E6  1               
00D2E6  1  A5 10            lda $10                     ; $D2E6: A5 10
00D2E8  1  D0 0D            bne UseBatterInputAction   ; $D2E8: D0 0D
00D2EA  1               
00D2EA  1  A5 9F            lda SecondaryActorState0      ; $D2EA: A5 9F
00D2EC  1  C9 02            cmp #$02                    ; $D2EC: C9 02
00D2EE  1  D0 07            bne UseBatterInputAction   ; $D2EE: D0 07
00D2F0  1               
00D2F0  1  20 F5 E5         jsr AdvanceRandomState                   ; $D2F0: 20 F5 E5
00D2F3  1  29 01            and #$01                    ; $D2F3: 29 01
00D2F5  1  10 02            bpl SaveBatterAction  ; $D2F5: 10 02
00D2F7  1                                               ; Always taken after AND #$01.
00D2F7  1               
00D2F7  1               UseBatterInputAction:          ; $D2F7
00D2F7  1  A5 14            lda InputState2             ; $D2F7: A5 14
00D2F9  1               
00D2F9  1               SaveBatterAction:         ; $D2F9
00D2F9  1  85 21            sta SelectedPitchAction          ; $D2F9: 85 21
00D2FB  1               
00D2FB  1               ; ----------------------------------------------------------------------------
00D2FB  1               ; Process event slots $0E and $11.
00D2FB  1               ; ----------------------------------------------------------------------------
00D2FB  1               
00D2FB  1  A0 0E            ldy #$0E                    ; $D2FB: A0 0E
00D2FD  1  20 66 EB         jsr DispatchNextQueuedEvent                   ; $D2FD: 20 66 EB
00D300  1               
00D300  1  A0 11            ldy #$11                    ; $D300: A0 11
00D302  1  20 66 EB         jsr DispatchNextQueuedEvent                   ; $D302: 20 66 EB
00D305  1               
00D305  1               ; ----------------------------------------------------------------------------
00D305  1               ; Initialize animation frame $0C, wait ten ticks, then run the helper at $D33C.
00D305  1               ; ----------------------------------------------------------------------------
00D305  1               
00D305  1  A9 0C            lda #$0C                    ; $D305: A9 0C
00D307  1  8D B7 03         sta $03B7                   ; $D307: 8D B7 03
00D30A  1               
00D30A  1  A9 0A            lda #$0A                    ; $D30A: A9 0A
00D30C  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $D30C: 20 41 EB
00D30F  1               
00D30F  1  20 3C D3         jsr DispatchActionType                   ; $D30F: 20 3C D3
00D312  1               
00D312  1  E6 9D            inc CurrentActionState             ; $D312: E6 9D
00D314  1  CE B7 03         dec $03B7                   ; $D314: CE B7 03
00D317  1               
00D317  1               ; ----------------------------------------------------------------------------
00D317  1               ; Dispatch the next state through an inline command.
00D317  1               ; ----------------------------------------------------------------------------
00D317  1               
00D317  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $D317: 20 0A EB
00D31A  1               
00D31A  1                   ; Inline command record consumed by QueueInlineObjectEvent.
00D31A  1  11 D7 D5         .byte $11,$D7,$D5           ; $D31A-$D31C
00D31D  1               
00D31D  1  A9 1E            lda #$1E                    ; $D31D: A9 1E
00D31F  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $D31F: 20 41 EB
00D322  1               
00D322  1  A9 2F            lda #$2F                    ; $D322: A9 2F
00D324  1  8D A2 03         sta $03A2                   ; $D324: 8D A2 03
00D327  1               
00D327  1  4C 6A EB         jmp CommonEngineExit                   ; $D327: 4C 6A EB
00D32A  1               
00D32A  1               ; ============================================================================
00D32A  1               ; $D32A-$D338
00D32A  1               ; Select an action value from a three-byte lookup table.
00D32A  1               ;
00D32A  1               ; Entry:
00D32A  1               ;   X = object or player index
00D32A  1               ;
00D32A  1               ; Operation:
00D32A  1               ;   1. Increment $7F.
00D32A  1               ;   2. Divide X by two.
00D32A  1               ;   3. Use the resulting index to read $0599-$059B.
00D32A  1               ;   4. Divide that value by two.
00D32A  1               ;   5. Use the result as an index into ObjectActionLookupTable.
00D32A  1               ;   6. Branch back to $D2F9 with the selected value in A.
00D32A  1               ;
00D32A  1               ; The table values are all nonzero, so the final BNE is effectively
00D32A  1               ; unconditional for valid indices.
00D32A  1               ; ============================================================================
00D32A  1               
00D32A  1               SelectActionFromObjectState:                   ; $D32A
00D32A  1  E6 7F            inc SelectedStateCount      ; $D32A: E6 7F
00D32C  1               
00D32C  1  8A               txa                         ; $D32C: 8A
00D32D  1  4A               lsr                         ; $D32D: 4A
00D32E  1  AA               tax                         ; $D32E: AA
00D32F  1               
00D32F  1  BD 99 05         lda $0599,x                 ; $D32F: BD 99 05
00D332  1  4A               lsr                         ; $D332: 4A
00D333  1  AA               tax                         ; $D333: AA
00D334  1               
00D334  1  BD 38 D3         lda $D338,x                 ; $D334: BD 38 D3
00D337  1  D0 C0            bne SaveBatterAction  ; $D337: D0 C0
00D339  1               
00D339  1               ; ============================================================================
00D339  1               ; $D339-$D33B
00D339  1               ; Action/control lookup table.
00D339  1               ;
00D339  1               ; Indexed by half of the selected value from $0599-$059B.
00D339  1               ; ============================================================================
00D339  1               
00D339  1               ObjectActionLookupTable:                     ; $D339
00D339  1  01 08 02         .byte $01,$08,$02
00D33C  1               
00D33C  1               ; ============================================================================
00D33C  1               ; $D33C-$D381
00D33C  1               ; Select one of three state paths using $21 and the values at $9F-$A1.
00D33C  1               ;
00D33C  1               ; The routine can:
00D33C  1               ;   Set $059D to $01 and dispatch command $10
00D33C  1               ;   Set $059E to $02 and dispatch command $12
00D33C  1               ;   Set $05A0 to $03 and dispatch command $16
00D33C  1               ; ============================================================================
00D33C  1               
00D33C  1               ; ----------------------------------------------------------------------------
00D33C  1               ; Contract:
00D33C  1               ;   Description: Implements Dispatch Action Type.
00D33C  1               ;   Entry: Registers: A, X; Memory: selectedpitchaction, secondaryactorstate0
00D33C  1               ;   Returns/products: Registers/clobbers: A, X
00D33C  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00D33C  1               ;   Memory effects: $059d
00D33C  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00D33C  1               ;          comparison, load, or store path and are not a stable API product.
00D33C  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00D33C  1               ; ----------------------------------------------------------------------------
00D33C  1               DispatchActionType:             ; $D33C
00D33C  1  A5 21            lda SelectedPitchAction          ; $D33C: A5 21
00D33E  1  29 0B            and #$0B                    ; $D33E: 29 0B
00D340  1  D0 1F            bne Routine_D361_TestBits   ; $D340: D0 1F
00D342  1               
00D342  1               ; ----------------------------------------------------------------------------
00D342  1               ; Search the three entries at $9F-$A1 in reverse order.
00D342  1               ; ----------------------------------------------------------------------------
00D342  1               
00D342  1  A2 02            ldx #$02                    ; $D342: A2 02
00D344  1               
00D344  1               Routine_D344_SearchEntries:     ; $D344
00D344  1  B5 9F            lda SecondaryActorState0,x    ; $D344: B5 9F
00D346  1  C9 08            cmp #$08                    ; $D346: C9 08
00D348  1  B0 08            bcs Routine_D352_NextEntry  ; $D348: B0 08
00D34A  1               
00D34A  1  C9 06            cmp #$06                    ; $D34A: C9 06
00D34C  1  B0 25            bcs Routine_D373_State3     ; $D34C: B0 25
00D34E  1               
00D34E  1  C9 04            cmp #$04                    ; $D34E: C9 04
00D350  1  B0 15            bcs Routine_D367_State2     ; $D350: B0 15
00D352  1               
00D352  1               Routine_D352_NextEntry:         ; $D352
00D352  1  CA               dex                         ; $D352: CA
00D353  1  10 EF            bpl Routine_D344_SearchEntries
00D355  1                                               ; $D353: 10 EF
00D355  1               
00D355  1               ; ----------------------------------------------------------------------------
00D355  1               ; State 1.
00D355  1               ; ----------------------------------------------------------------------------
00D355  1               
00D355  1               Routine_D355_State1:            ; $D355
00D355  1  A9 01            lda #$01                    ; $D355: A9 01
00D357  1  8D 9D 05         sta $059D                   ; $D357: 8D 9D 05
00D35A  1               
00D35A  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $D35A: 20 0A EB
00D35D  1               
00D35D  1                   ; Inline command record consumed by QueueInlineObjectEvent.
00D35D  1  10 AB E3         .byte $10,$AB,$E3           ; $D35D-$D35F
00D360  1               
00D360  1  60               rts                         ; $D360: 60
00D361  1               
00D361  1               ; ----------------------------------------------------------------------------
00D361  1               ; When $21 & $0B is nonzero, test its low two bits.
00D361  1               ;
00D361  1               ; Bit 0 selects state 1.
00D361  1               ; Bit 1 selects state 3.
00D361  1               ; Otherwise, state 2 is selected.
00D361  1               ; ----------------------------------------------------------------------------
00D361  1               
00D361  1               Routine_D361_TestBits:          ; $D361
00D361  1  4A               lsr                         ; $D361: 4A
00D362  1  B0 F1            bcs Routine_D355_State1     ; $D362: B0 F1
00D364  1               
00D364  1  4A               lsr                         ; $D364: 4A
00D365  1  B0 0C            bcs Routine_D373_State3     ; $D365: B0 0C
00D367  1               
00D367  1               ; ----------------------------------------------------------------------------
00D367  1               ; State 2.
00D367  1               ; ----------------------------------------------------------------------------
00D367  1               
00D367  1               Routine_D367_State2:            ; $D367
00D367  1  A9 02            lda #$02                    ; $D367: A9 02
00D369  1  8D 9E 05         sta $059E                   ; $D369: 8D 9E 05
00D36C  1               
00D36C  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $D36C: 20 0A EB
00D36F  1               
00D36F  1                   ; Inline command record consumed by QueueInlineObjectEvent.
00D36F  1  12 AB E3         .byte $12,$AB,$E3           ; $D36F-$D371
00D372  1               
00D372  1  60               rts                         ; $D372: 60
00D373  1               
00D373  1               ; ----------------------------------------------------------------------------
00D373  1               ; State 3.
00D373  1               ; ----------------------------------------------------------------------------
00D373  1               
00D373  1               Routine_D373_State3:            ; $D373
00D373  1  A9 03            lda #$03                    ; $D373: A9 03
00D375  1  8D A0 05         sta $05A0                   ; $D375: 8D A0 05
00D378  1               
00D378  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $D378: 20 0A EB
00D37B  1               
00D37B  1                   ; Inline command record consumed by QueueInlineObjectEvent.
00D37B  1  16 AB E3         .byte $16,$AB,$E3           ; $D37B-$D37D
00D37E  1               
00D37E  1  CE B7 03         dec $03B7                   ; $D37E: CE B7 03
00D381  1               
00D381  1  60               rts                         ; $D381: 60
00D382  1               
00D382  1               ; ============================================================================
00D382  1               ; $D382-$D3EF
00D382  1               ; Derive an index from input state, apply signed coordinate offsets, constrain
00D382  1               ; the resulting positions, update object state, and repeat.
00D382  1               ; ============================================================================
00D382  1               
00D382  1               MoveControlledObject:                   ; $D382
00D382  1  20 48 EB         jsr SelectObjectEventBank1                   ; $D382: 20 48 EB
00D385  1               
00D385  1               ; ----------------------------------------------------------------------------
00D385  1               ; Derive a small index in Y from the value at $13.
00D385  1               ;
00D385  1               ; The value is ORed with $F0, then shifted right until carry clears.
00D385  1               ; Y begins at $FF and is incremented once per shift.
00D385  1               ; ----------------------------------------------------------------------------
00D385  1               
00D385  1  A0 FF            ldy #$FF                    ; $D385: A0 FF
00D387  1               
00D387  1  A5 13            lda InputState1             ; $D387: A5 13
00D389  1  09 F0            ora #$F0                    ; $D389: 09 F0
00D38B  1               
00D38B  1               Routine_D38B_FindIndex:         ; $D38B
00D38B  1  C8               iny                         ; $D38B: C8
00D38C  1  4A               lsr                         ; $D38C: 4A
00D38D  1  90 FC            bcc Routine_D38B_FindIndex  ; $D38D: 90 FC
00D38F  1               
00D38F  1  84 05            sty MathTemp05              ; $D38F: 84 05
00D391  1               
00D391  1               ; ----------------------------------------------------------------------------
00D391  1               ; Load a signed horizontal offset from the table at $D3F0.
00D391  1               ;
00D391  1               ; X is used as the sign-extension byte:
00D391  1               ;
00D391  1               ;   X = $00 for nonnegative offsets
00D391  1               ;   X = $FF for negative offsets
00D391  1               ; ----------------------------------------------------------------------------
00D391  1               
00D391  1  A2 00            ldx #$00                    ; $D391: A2 00
00D393  1               
00D393  1  B9 F0 D3         lda ControlledHorizontalOffsetTable,y            ; $D393: B9 F0 D3
00D396  1  10 01            bpl Routine_D399_AddHorizontal
00D398  1                                               ; $D396: 10 01
00D398  1               
00D398  1  CA               dex                         ; $D398: CA
00D399  1                                               ; X = $FF
00D399  1               
00D399  1               Routine_D399_AddHorizontal:     ; $D399
00D399  1  18               clc                         ; $D399: 18
00D39A  1               
00D39A  1  6D 0F 05         adc $050F                   ; $D39A: 6D 0F 05
00D39D  1  A8               tay                         ; $D39D: A8
00D39E  1  85 AE            sta CalculatedCoordinateLow        ; $D39E: 85 AE
00D3A0  1               
00D3A0  1  8A               txa                         ; $D3A0: 8A
00D3A1  1  6D 10 05         adc $0510                   ; $D3A1: 6D 10 05
00D3A4  1  85 AF            sta CalculatedCoordinateHigh        ; $D3A4: 85 AF
00D3A6  1               
00D3A6  1               ; ----------------------------------------------------------------------------
00D3A6  1               ; Normalize or transform the signed horizontal coordinate in A:Y.
00D3A6  1               ; ----------------------------------------------------------------------------
00D3A6  1               
00D3A6  1  20 CB E7         jsr AbsoluteValueAY                   ; $D3A6: 20 CB E7
00D3A9  1  AA               tax                         ; $D3A9: AA
00D3AA  1               
00D3AA  1               ; ----------------------------------------------------------------------------
00D3AA  1               ; Accept the new horizontal coordinate only when it lies inside the permitted
00D3AA  1               ; range.
00D3AA  1               ;
00D3AA  1               ; The two-stage signed test uses Y as the low byte and X/A as the high byte.
00D3AA  1               ; ----------------------------------------------------------------------------
00D3AA  1               
00D3AA  1  C0 60            cpy #$60                    ; $D3AA: C0 60
00D3AC  1  E9 01            sbc #$01                    ; $D3AC: E9 01
00D3AE  1  10 11            bpl Routine_D3C1_Vertical   ; $D3AE: 10 11
00D3B0  1               
00D3B0  1  8A               txa                         ; $D3B0: 8A
00D3B1  1               
00D3B1  1  C0 00            cpy #$00                    ; $D3B1: C0 00
00D3B3  1  E9 01            sbc #$01                    ; $D3B3: E9 01
00D3B5  1  30 0A            bmi Routine_D3C1_Vertical   ; $D3B5: 30 0A
00D3B7  1               
00D3B7  1  A5 AE            lda CalculatedCoordinateLow        ; $D3B7: A5 AE
00D3B9  1  8D 0F 05         sta $050F                   ; $D3B9: 8D 0F 05
00D3BC  1               
00D3BC  1  A5 AF            lda CalculatedCoordinateHigh        ; $D3BC: A5 AF
00D3BE  1  8D 10 05         sta $0510                   ; $D3BE: 8D 10 05
00D3C1  1               
00D3C1  1               ; ----------------------------------------------------------------------------
00D3C1  1               ; Load a signed vertical offset from the overlapping table at $D3F3.
00D3C1  1               ; ----------------------------------------------------------------------------
00D3C1  1               
00D3C1  1               Routine_D3C1_Vertical:          ; $D3C1
00D3C1  1  A4 05            ldy MathTemp05              ; $D3C1: A4 05
00D3C3  1  A2 00            ldx #$00                    ; $D3C3: A2 00
00D3C5  1               
00D3C5  1  B9 F3 D3         lda ControlledVerticalOffsetTable,y            ; $D3C5: B9 F3 D3
00D3C8  1  10 01            bpl Routine_D3CB_AddVertical
00D3CA  1                                               ; $D3C8: 10 01
00D3CA  1               
00D3CA  1  CA               dex                         ; $D3CA: CA
00D3CB  1                                               ; X = $FF
00D3CB  1               
00D3CB  1               Routine_D3CB_AddVertical:       ; $D3CB
00D3CB  1  18               clc                         ; $D3CB: 18
00D3CC  1               
00D3CC  1  6D 40 05         adc $0540                   ; $D3CC: 6D 40 05
00D3CF  1  A8               tay                         ; $D3CF: A8
00D3D0  1               
00D3D0  1  8A               txa                         ; $D3D0: 8A
00D3D1  1  6D 41 05         adc $0541                   ; $D3D1: 6D 41 05
00D3D4  1  AA               tax                         ; $D3D4: AA
00D3D5  1               
00D3D5  1               ; ----------------------------------------------------------------------------
00D3D5  1               ; Accept the vertical coordinate only when it lies inside the permitted range.
00D3D5  1               ; ----------------------------------------------------------------------------
00D3D5  1               
00D3D5  1  C0 C0            cpy #$C0                    ; $D3D5: C0 C0
00D3D7  1  E9 F8            sbc #$F8                    ; $D3D7: E9 F8
00D3D9  1  10 0D            bpl Routine_D3E8_UpdateObject
00D3DB  1                                               ; $D3D9: 10 0D
00D3DB  1               
00D3DB  1  8A               txa                         ; $D3DB: 8A
00D3DC  1               
00D3DC  1  C0 A0            cpy #$A0                    ; $D3DC: C0 A0
00D3DE  1  E9 F7            sbc #$F7                    ; $D3DE: E9 F7
00D3E0  1  30 06            bmi Routine_D3E8_UpdateObject
00D3E2  1                                               ; $D3E0: 30 06
00D3E2  1               
00D3E2  1  8C 40 05         sty $0540                   ; $D3E2: 8C 40 05
00D3E5  1  8E 41 05         stx $0541                   ; $D3E5: 8E 41 05
00D3E8  1               
00D3E8  1               ; ----------------------------------------------------------------------------
00D3E8  1               ; Update object six, then repeat the routine.
00D3E8  1               ; ----------------------------------------------------------------------------
00D3E8  1               
00D3E8  1               Routine_D3E8_UpdateObject:      ; $D3E8
00D3E8  1  A2 06            ldx #$06                    ; $D3E8: A2 06
00D3EA  1  20 B7 E6         jsr ClearMovementTransforms                   ; $D3EA: 20 B7 E6
00D3ED  1               
00D3ED  1  4C 82 D3         jmp MoveControlledObject            ; $D3ED: 4C 82 D3
00D3F0  1               
00D3F0  1               ; ============================================================================
00D3F0  1               ; Temporary aliases for the lookup data immediately following the routine.
00D3F0  1               ; Remove these aliases when the $D3F0 data block is decoded.
00D3F0  1               ; ============================================================================
00D3F0  1               
00D3F0  1               ControlledHorizontalOffsetTable:                     ; $D3F0
00D3F0  1  01 FF 00         .byte $01,$FF,$00
00D3F3  1               
00D3F3  1               ControlledVerticalOffsetTable:                     ; $D3F3
00D3F3  1  00 00 FF 01      .byte $00,$00,$FF,$01,$00
00D3F7  1  00           
00D3F8  1               
00D3F8  1               ; ============================================================================
00D3F8  1               ; $D3F8-$D477
00D3F8  1               ; Randomized timing and coordinate-validation routine.
00D3F8  1               ; ============================================================================
00D3F8  1               
00D3F8  1               RunControlledActorDelay:                   ; $D3F8
00D3F8  1  A9 14            lda #$14                    ; $D3F8: A9 14
00D3FA  1  85 92            sta ActionDelayCounter           ; $D3FA: 85 92
00D3FC  1               
00D3FC  1               ; ----------------------------------------------------------------------------
00D3FC  1               ; Run $EB4C twenty times while setting $13 to $80 between iterations.
00D3FC  1               ; ----------------------------------------------------------------------------
00D3FC  1               
00D3FC  1               Routine_D3FC_InitialDelay:      ; $D3FC
00D3FC  1  20 4C EB         jsr SelectObjectEventBank0                   ; $D3FC: 20 4C EB
00D3FF  1               
00D3FF  1  A9 80            lda #$80                    ; $D3FF: A9 80
00D401  1  85 13            sta InputState1             ; $D401: 85 13
00D403  1               
00D403  1  C6 92            dec ActionDelayCounter           ; $D403: C6 92
00D405  1  D0 F5            bne Routine_D3FC_InitialDelay
00D407  1                                               ; $D405: D0 F5
00D407  1               
00D407  1               ; ----------------------------------------------------------------------------
00D407  1               ; Generate a random value from zero through ten.
00D407  1               ; ----------------------------------------------------------------------------
00D407  1               
00D407  1               SelectControlledActorDelay:      ; $D407
00D407  1  20 F5 E5         jsr AdvanceRandomState                   ; $D407: 20 F5 E5
00D40A  1               
00D40A  1  29 0F            and #$0F                    ; $D40A: 29 0F
00D40C  1  C9 0B            cmp #$0B                    ; $D40C: C9 0B
00D40E  1  B0 F7            bcs SelectControlledActorDelay
00D410  1                                               ; $D40E: B0 F7
00D410  1               
00D410  1               ; ----------------------------------------------------------------------------
00D410  1               ; Convert values ten and below into a signed countdown-like value.
00D410  1               ;
00D410  1               ; Carry remains set after CMP when A is ten, otherwise it is clear. The
00D410  1               ; subtraction intentionally uses that carry state.
00D410  1               ; ----------------------------------------------------------------------------
00D410  1               
00D410  1  E9 0A            sbc #$0A                    ; $D410: E9 0A
00D412  1  85 92            sta ActionDelayCounter           ; $D412: 85 92
00D414  1               
00D414  1               ; ----------------------------------------------------------------------------
00D414  1               ; Wait until the high position byte at $053B becomes negative.
00D414  1               ; ----------------------------------------------------------------------------
00D414  1               
00D414  1               WaitForActorAscent:   ; $D414
00D414  1  20 48 EB         jsr SelectObjectEventBank1                   ; $D414: 20 48 EB
00D417  1               
00D417  1  AE 3B 05         ldx $053B                   ; $D417: AE 3B 05
00D41A  1  CA               dex                         ; $D41A: CA
00D41B  1  10 F7            bpl WaitForActorAscent
00D41D  1                                               ; $D41B: 10 F7
00D41D  1               
00D41D  1               ; ----------------------------------------------------------------------------
00D41D  1               ; Increment the countdown and wait until $053B reaches at least $FD.
00D41D  1               ; ----------------------------------------------------------------------------
00D41D  1               
00D41D  1               WaitForActorDescent:       ; $D41D
00D41D  1  E6 92            inc ActionDelayCounter           ; $D41D: E6 92
00D41F  1               
00D41F  1  20 48 EB         jsr SelectObjectEventBank1                   ; $D41F: 20 48 EB
00D422  1               
00D422  1  AD 3B 05         lda $053B                   ; $D422: AD 3B 05
00D425  1  C9 FD            cmp #$FD                    ; $D425: C9 FD
00D427  1  10 F4            bpl WaitForActorDescent
00D429  1                                               ; $D427: 10 F4
00D429  1               
00D429  1               ; ----------------------------------------------------------------------------
00D429  1               ; Generate a random byte. Values below two take the alternate timing path.
00D429  1               ; ----------------------------------------------------------------------------
00D429  1               
00D429  1  20 F5 E5         jsr AdvanceRandomState                   ; $D429: 20 F5 E5
00D42C  1               
00D42C  1  C9 02            cmp #$02                    ; $D42C: C9 02
00D42E  1  90 31            bcc SelectActorAlternateDelay
00D430  1                                               ; $D42E: 90 31
00D430  1               
00D430  1               ; ----------------------------------------------------------------------------
00D430  1               ; Normalize the current horizontal position in A:Y.
00D430  1               ; ----------------------------------------------------------------------------
00D430  1               
00D430  1  AA               tax                         ; $D430: AA
00D431  1               
00D431  1  AC 09 05         ldy $0509                   ; $D431: AC 09 05
00D434  1  AD 0A 05         lda $050A                   ; $D434: AD 0A 05
00D437  1               
00D437  1  20 CB E7         jsr AbsoluteValueAY                   ; $D437: 20 CB E7
00D43A  1               
00D43A  1               ; ----------------------------------------------------------------------------
00D43A  1               ; Validate the normalized coordinate against two bounds.
00D43A  1               ;
00D43A  1               ; X still contains the random byte selected at $D429.
00D43A  1               ; ----------------------------------------------------------------------------
00D43A  1               
00D43A  1  E0 DC            cpx #$DC                    ; $D43A: E0 DC
00D43C  1  B0 37            bcs FinishControlledActorDelay       ; $D43C: B0 37
00D43E  1               
00D43E  1  C0 20            cpy #$20                    ; $D43E: C0 20
00D440  1  E9 00            sbc #$00                    ; $D440: E9 00
00D442  1  90 04            bcc RunActorDelayCountdown  ; $D442: 90 04
00D444  1               
00D444  1  E0 38            cpx #$38                    ; $D444: E0 38
00D446  1  B0 2D            bcs FinishControlledActorDelay       ; $D446: B0 2D
00D448  1               
00D448  1               ; ----------------------------------------------------------------------------
00D448  1               ; Wait while counting $92 down through zero.
00D448  1               ; ----------------------------------------------------------------------------
00D448  1               
00D448  1               RunActorDelayCountdown:         ; $D448
00D448  1  20 48 EB         jsr SelectObjectEventBank1                   ; $D448: 20 48 EB
00D44B  1               
00D44B  1  C6 92            dec ActionDelayCounter           ; $D44B: C6 92
00D44D  1  10 F9            bpl RunActorDelayCountdown  ; $D44D: 10 F9
00D44F  1               
00D44F  1               ; ----------------------------------------------------------------------------
00D44F  1               ; Run another fixed twenty-iteration delay.
00D44F  1               ; ----------------------------------------------------------------------------
00D44F  1               
00D44F  1  A9 14            lda #$14                    ; $D44F: A9 14
00D451  1  85 92            sta ActionDelayCounter           ; $D451: 85 92
00D453  1               
00D453  1               RunActorFinalDelay:        ; $D453
00D453  1  20 4C EB         jsr SelectObjectEventBank0                   ; $D453: 20 4C EB
00D456  1               
00D456  1  A9 80            lda #$80                    ; $D456: A9 80
00D458  1  85 13            sta InputState1             ; $D458: 85 13
00D45A  1               
00D45A  1  C6 92            dec ActionDelayCounter           ; $D45A: C6 92
00D45C  1  D0 F5            bne RunActorFinalDelay ; $D45C: D0 F5
00D45E  1               
00D45E  1  4C 6A EB         jmp CommonEngineExit                   ; $D45E: 4C 6A EB
00D461  1               
00D461  1               ; ----------------------------------------------------------------------------
00D461  1               ; Alternate randomized delay path for values below two.
00D461  1               ; ----------------------------------------------------------------------------
00D461  1               
00D461  1               SelectActorAlternateDelay:    ; $D461
00D461  1  20 F5 E5         jsr AdvanceRandomState                   ; $D461: 20 F5 E5
00D464  1               
00D464  1  29 07            and #$07                    ; $D464: 29 07
00D466  1  69 04            adc #$04                    ; $D466: 69 04
00D468  1  85 92            sta ActionDelayCounter           ; $D468: 85 92
00D46A  1               
00D46A  1               RunActorAlternateDelay:     ; $D46A
00D46A  1  20 4C EB         jsr SelectObjectEventBank0                   ; $D46A: 20 4C EB
00D46D  1               
00D46D  1  A9 80            lda #$80                    ; $D46D: A9 80
00D46F  1  85 13            sta InputState1             ; $D46F: 85 13
00D471  1               
00D471  1  C6 92            dec ActionDelayCounter           ; $D471: C6 92
00D473  1  D0 F5            bne RunActorAlternateDelay
00D475  1                                               ; $D473: D0 F5
00D475  1               
00D475  1               FinishControlledActorDelay:              ; $D475
00D475  1  4C 6A EB         jmp CommonEngineExit                   ; $D475: 4C 6A EB
00D478  1               
00D478  1               ; ============================================================================
00D478  1               ; $D478-$D4FE
00D478  1               ; Initialize object six, transform coordinates, and run a state-controlled
00D478  1               ; animation loop.
00D478  1               ; ============================================================================
00D478  1               
00D478  1               RunFielderAnimationSequence:                   ; $D478
00D478  1  A9 00            lda #$00                    ; $D478: A9 00
00D47A  1  85 87            sta ObjectProximityState                 ; $D47A: 85 87
00D47C  1               
00D47C  1               ; ----------------------------------------------------------------------------
00D47C  1               ; Initialize indexed fields for object offset $06.
00D47C  1               ;
00D47C  1               ; Routine $C9A7 consumes five inline bytes:
00D47C  1               ;
00D47C  1               ;   $06                 object offset/metadata
00D47C  1               ;   $F0,$FE,$20,$F8     four field values
00D47C  1               ; ----------------------------------------------------------------------------
00D47C  1               
00D47C  1  20 A7 C9         jsr LoadObjectPositionInline
00D47F  1                                               ; $D47C: 20 A7 C9
00D47F  1               
00D47F  1  06               .byte $06                   ; $D47F
00D480  1  F0 FE 20 F8      .byte $F0,$FE,$20,$F8       ; $D480-$D483
00D484  1               
00D484  1               ; ----------------------------------------------------------------------------
00D484  1               ; XOR both bytes of the coordinate at $050F/$0510 with $4C.
00D484  1               ; ----------------------------------------------------------------------------
00D484  1               
00D484  1  AD 0F 05         lda $050F                   ; $D484: AD 0F 05
00D487  1  45 4C            eor HorizontalDirectionMask           ; $D487: 45 4C
00D489  1  8D 0F 05         sta $050F                   ; $D489: 8D 0F 05
00D48C  1               
00D48C  1  AD 10 05         lda $0510                   ; $D48C: AD 10 05
00D48F  1  45 4C            eor HorizontalDirectionMask           ; $D48F: 45 4C
00D491  1  8D 10 05         sta $0510                   ; $D491: 8D 10 05
00D494  1               
00D494  1               ; ----------------------------------------------------------------------------
00D494  1               ; Initialize animation and timing state.
00D494  1               ; ----------------------------------------------------------------------------
00D494  1               
00D494  1  A9 00            lda #$00                    ; $D494: A9 00
00D496  1  8D B3 03         sta $03B3                   ; $D496: 8D B3 03
00D499  1               
00D499  1  A9 1E            lda #$1E                    ; $D499: A9 1E
00D49B  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $D49B: 20 41 EB
00D49E  1               
00D49E  1               ; ----------------------------------------------------------------------------
00D49E  1               ; Shared loop restart point.
00D49E  1               ; ----------------------------------------------------------------------------
00D49E  1               
00D49E  1               ResetFielderAnimationCounters:     ; $D49E
00D49E  1  A9 00            lda #$00                    ; $D49E: A9 00
00D4A0  1  85 8D            sta FielderInputBalance       ; $D4A0: 85 8D
00D4A2  1               
00D4A2  1  A9 0B            lda #$0B                    ; $D4A2: A9 0B
00D4A4  1  85 8C            sta FielderAnimationCountdown      ; $D4A4: 85 8C
00D4A6  1               
00D4A6  1               ; ----------------------------------------------------------------------------
00D4A6  1               ; Wait until $13 becomes negative.
00D4A6  1               ; ----------------------------------------------------------------------------
00D4A6  1               
00D4A6  1               WaitForFielderInput:      ; $D4A6
00D4A6  1  20 48 EB         jsr SelectObjectEventBank1                   ; $D4A6: 20 48 EB
00D4A9  1               
00D4A9  1  A5 13            lda InputState1             ; $D4A9: A5 13
00D4AB  1  10 F9            bpl WaitForFielderInput
00D4AD  1                                               ; $D4AB: 10 F9
00D4AD  1               
00D4AD  1               ; ----------------------------------------------------------------------------
00D4AD  1               ; Initialize the per-cycle counter and advance the animation.
00D4AD  1               ; ----------------------------------------------------------------------------
00D4AD  1               
00D4AD  1               AdvanceFielderAnimationCycle:         ; $D4AD
00D4AD  1  A9 03            lda #$03                    ; $D4AD: A9 03
00D4AF  1  85 0C            sta $0C                     ; $D4AF: 85 0C
00D4B1  1               
00D4B1  1  EE B3 03         inc $03B3                   ; $D4B1: EE B3 03
00D4B4  1               
00D4B4  1               ; ----------------------------------------------------------------------------
00D4B4  1               ; A state condition at $82/$87 can branch to the next routine at $D4FF.
00D4B4  1               ; ----------------------------------------------------------------------------
00D4B4  1               
00D4B4  1               CheckFielderAnimationState:        ; $D4B4
00D4B4  1  A5 82            lda ActorActionComplete                 ; $D4B4: A5 82
00D4B6  1  D0 06            bne UpdateFielderAnimationFrame  ; $D4B6: D0 06
00D4B8  1               
00D4B8  1  A5 87            lda ObjectProximityState                 ; $D4B8: A5 87
00D4BA  1  C9 01            cmp #$01                    ; $D4BA: C9 01
00D4BC  1  F0 41            beq SelectRandomMotionParameters            ; $D4BC: F0 41
00D4BE  1               
00D4BE  1               ; ----------------------------------------------------------------------------
00D4BE  1               ; Wait one frame and compare the animation value against five.
00D4BE  1               ; ----------------------------------------------------------------------------
00D4BE  1               
00D4BE  1               UpdateFielderAnimationFrame:         ; $D4BE
00D4BE  1  20 48 EB         jsr SelectObjectEventBank1                   ; $D4BE: 20 48 EB
00D4C1  1               
00D4C1  1  38               sec                         ; $D4C1: 38
00D4C2  1               
00D4C2  1  AD B3 03         lda $03B3                   ; $D4C2: AD B3 03
00D4C5  1  E9 05            sbc #$05                    ; $D4C5: E9 05
00D4C7  1  F0 1E            beq ReverseFielderAnimation ; $D4C7: F0 1E
00D4C9  1               
00D4C9  1               ; ----------------------------------------------------------------------------
00D4C9  1               ; Adjust $8D according to the sign of $13.
00D4C9  1               ; ----------------------------------------------------------------------------
00D4C9  1               
00D4C9  1  A5 13            lda InputState1             ; $D4C9: A5 13
00D4CB  1  30 08            bmi UpdateFielderAnimationCounters
00D4CD  1                                               ; $D4CB: 30 08
00D4CD  1               
00D4CD  1  C6 8D            dec FielderInputBalance       ; $D4CD: C6 8D
00D4CF  1  10 E3            bpl CheckFielderAnimationState ; $D4CF: 10 E3
00D4D1  1               
00D4D1  1  E6 8D            inc FielderInputBalance       ; $D4D1: E6 8D
00D4D3  1  10 DF            bpl CheckFielderAnimationState ; $D4D3: 10 DF
00D4D5  1               
00D4D5  1               ; ----------------------------------------------------------------------------
00D4D5  1               ; Update loop counters.
00D4D5  1               ; ----------------------------------------------------------------------------
00D4D5  1               
00D4D5  1               UpdateFielderAnimationCounters:   ; $D4D5
00D4D5  1  E6 8D            inc FielderInputBalance       ; $D4D5: E6 8D
00D4D7  1               
00D4D7  1  C6 8C            dec FielderAnimationCountdown      ; $D4D7: C6 8C
00D4D9  1  C6 0C            dec $0C                     ; $D4D9: C6 0C
00D4DB  1  D0 D7            bne CheckFielderAnimationState ; $D4DB: D0 D7
00D4DD  1               
00D4DD  1               ; ----------------------------------------------------------------------------
00D4DD  1               ; Repeat until the animation value reaches five.
00D4DD  1               ; ----------------------------------------------------------------------------
00D4DD  1               
00D4DD  1  AE B3 03         ldx $03B3                   ; $D4DD: AE B3 03
00D4E0  1  E0 05            cpx #$05                    ; $D4E0: E0 05
00D4E2  1  F0 DA            beq UpdateFielderAnimationFrame  ; $D4E2: F0 DA
00D4E4  1               
00D4E4  1  4C AD D4         jmp AdvanceFielderAnimationCycle  ; $D4E4: 4C AD D4
00D4E7  1               
00D4E7  1               ; ----------------------------------------------------------------------------
00D4E7  1               ; Handle animation value five.
00D4E7  1               ; ----------------------------------------------------------------------------
00D4E7  1               
00D4E7  1               ReverseFielderAnimation:        ; $D4E7
00D4E7  1  85 8D            sta FielderInputBalance                     ; $D4E7: 85 8D
00D4E9  1                                               ; A is zero after SBC #$05 succeeded.
00D4E9  1               
00D4E9  1  A5 13            lda InputState1             ; $D4E9: A5 13
00D4EB  1  30 D1            bmi UpdateFielderAnimationFrame  ; $D4EB: 30 D1
00D4ED  1               
00D4ED  1  CE B3 03         dec $03B3                   ; $D4ED: CE B3 03
00D4F0  1               
00D4F0  1  A9 02            lda #$02                    ; $D4F0: A9 02
00D4F2  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $D4F2: 20 41 EB
00D4F5  1               
00D4F5  1  AD B3 03         lda $03B3                   ; $D4F5: AD B3 03
00D4F8  1  C9 00            cmp #$00                    ; $D4F8: C9 00
00D4FA  1  D0 EB            bne ReverseFielderAnimation ; $D4FA: D0 EB
00D4FC  1               
00D4FC  1  4C 9E D4         jmp ResetFielderAnimationCounters
00D4FF  1                                               ; $D4FC: 4C 9E D4
00D4FF  1               
00D4FF  1               
00D4FF  1               ; ============================================================================
00D4FF  1               ; $D4FF-$D51B
00D4FF  1               ; Select a threshold index and calculate a randomized value.
00D4FF  1               ; ============================================================================
00D4FF  1               
00D4FF  1               SelectRandomMotionParameters:                   ; $D4FF
00D4FF  1  A2 05            ldx #$05                    ; $D4FF: A2 05
00D501  1               
00D501  1               ; ----------------------------------------------------------------------------
00D501  1               ; Generate one random value.
00D501  1               ;
00D501  1               ; The same random value is compared against multiple thresholds while X
00D501  1               ; counts downward. The loop at $D50A returns to the CMP at $D504, not to the
00D501  1               ; random-number call.
00D501  1               ; ----------------------------------------------------------------------------
00D501  1               
00D501  1  20 F5 E5         jsr AdvanceRandomState                   ; $D501: 20 F5 E5
00D504  1               
00D504  1               SearchMotionThreshold:  ; $D504
00D504  1  DD BD D5         cmp $D5BD,x                 ; $D504: DD BD D5
00D507  1  B0 07            bcs StartRandomMotion    ; $D507: B0 07
00D509  1               
00D509  1  CA               dex                         ; $D509: CA
00D50A  1  D0 F8            bne SearchMotionThreshold
00D50C  1                                               ; $D50A: D0 F8
00D50C  1               
00D50C  1               ; ----------------------------------------------------------------------------
00D50C  1               ; No nonzero threshold index was selected.
00D50C  1               ;
00D50C  1               ; X is zero here. Save it to $81 and branch back to the earlier wait loop.
00D50C  1               ; ----------------------------------------------------------------------------
00D50C  1               
00D50C  1  86 81            stx RandomValue81           ; $D50C: 86 81
00D50E  1  F0 AE            beq UpdateFielderAnimationFrame  ; $D50E: F0 AE
00D510  1                                               ; Always taken because X is zero.
00D510  1               
00D510  1               ; ----------------------------------------------------------------------------
00D510  1               ; A threshold was selected.
00D510  1               ;
00D510  1               ; Advance state and combine a new random value with the indexed base value at
00D510  1               ; $D5B8,X.
00D510  1               ; ----------------------------------------------------------------------------
00D510  1               
00D510  1               StartRandomMotion:           ; $D510
00D510  1  E6 46            inc StateSequenceActive             ; $D510: E6 46
00D512  1               
00D512  1  20 F5 E5         jsr AdvanceRandomState                   ; $D512: 20 F5 E5
00D515  1  29 1F            and #$1F                    ; $D515: 29 1F
00D517  1               
00D517  1  7D B8 D5         adc $D5B8,x                 ; $D517: 7D B8 D5
00D51A  1  85 8E            sta RandomHorizontalMotion          ; $D51A: 85 8E
00D51C  1               
00D51C  1               ; ============================================================================
00D51C  1               ; $D51C-$D53F
00D51C  1               ; Select a second table index and perform the first signed calculation.
00D51C  1               ; ============================================================================
00D51C  1               
00D51C  1  A2 0A            ldx #$0A                    ; $D51C: A2 0A
00D51E  1               
00D51E  1  A5 8D            lda FielderInputBalance       ; $D51E: A5 8D
00D520  1  85 88            sta MotionDirectionState                 ; $D520: 85 88
00D522  1  F0 09            beq SelectRandomMotionOffset
00D524  1                                               ; $D522: F0 09
00D524  1               
00D524  1               ; ----------------------------------------------------------------------------
00D524  1               ; Generate random values until one satisfies a threshold selected from the
00D524  1               ; table using base address $D5CE.
00D524  1               ;
00D524  1               ; X is decremented before each comparison.
00D524  1               ; ----------------------------------------------------------------------------
00D524  1               
00D524  1               SearchMotionAngleThreshold:   ; $D524
00D524  1  20 F5 E5         jsr AdvanceRandomState                   ; $D524: 20 F5 E5
00D527  1               
00D527  1               CompareMotionAngleThreshold:  ; $D527
00D527  1  CA               dex                         ; $D527: CA
00D528  1               
00D528  1  DD CE D5         cmp $D5CE,x                 ; $D528: DD CE D5
00D52B  1  90 FA            bcc CompareMotionAngleThreshold
00D52D  1                                               ; $D52B: 90 FA
00D52D  1               
00D52D  1               ; ----------------------------------------------------------------------------
00D52D  1               ; Generate another random value. Its low bit is added to the indexed value
00D52D  1               ; read using table base $D5C3.
00D52D  1               ; ----------------------------------------------------------------------------
00D52D  1               
00D52D  1               SelectRandomMotionOffset:      ; $D52D
00D52D  1  20 F5 E5         jsr AdvanceRandomState                   ; $D52D: 20 F5 E5
00D530  1               
00D530  1  29 01            and #$01                    ; $D530: 29 01
00D532  1  7D C3 D5         adc $D5C3,x                 ; $D532: 7D C3 D5
00D535  1  A8               tay                         ; $D535: A8
00D536  1               
00D536  1               ; ----------------------------------------------------------------------------
00D536  1               ; Pass A = $8E, X = 0, and the selected Y value to the math helper at $E855.
00D536  1               ;
00D536  1               ; Save the returned Y value in $8F and preserve A on the stack.
00D536  1               ; ----------------------------------------------------------------------------
00D536  1               
00D536  1  A2 00            ldx #$00                    ; $D536: A2 00
00D538  1               
00D538  1  A5 8E            lda RandomHorizontalMotion          ; $D538: A5 8E
00D53A  1  20 55 E8         jsr CalculateVectorFromRotatedMask                   ; $D53A: 20 55 E8
00D53D  1               
00D53D  1  84 8F            sty CalculatedVerticalMotion            ; $D53D: 84 8F
00D53F  1  48               pha                         ; $D53F: 48
00D540  1               
00D540  1               ; ============================================================================
00D540  1               ; $D540-$D560
00D540  1               ; Construct a randomized signed value in $90, perform a second calculation,
00D540  1               ; then pass both calculated values to InitializeBaseMotion.
00D540  1               ;
00D540  1               ; Entry:
00D540  1               ;   A contains the first result from $E855, preserved on the stack.
00D540  1               ;   Y contains the corresponding secondary result.
00D540  1               ; ============================================================================
00D540  1               
00D540  1  38               sec                         ; $D540: 38
00D541  1               
00D541  1  A5 8C            lda FielderAnimationCountdown      ; $D541: A5 8C
00D543  1  E9 05            sbc #$05                    ; $D543: E9 05
00D545  1               
00D545  1               ; ----------------------------------------------------------------------------
00D545  1               ; Scale the signed result.
00D545  1               ;
00D545  1               ; SEC followed by ROL shifts the value left while forcing bit zero to one.
00D545  1               ; Three additional ASL instructions multiply the result by eight.
00D545  1               ; ----------------------------------------------------------------------------
00D545  1               
00D545  1  38               sec                         ; $D545: 38
00D546  1  2A               rol                         ; $D546: 2A
00D547  1  0A               asl                         ; $D547: 0A
00D548  1  0A               asl                         ; $D548: 0A
00D549  1  0A               asl                         ; $D549: 0A
00D54A  1               
00D54A  1  85 90            sta RandomVerticalMotion          ; $D54A: 85 90
00D54C  1               
00D54C  1               ; ----------------------------------------------------------------------------
00D54C  1               ; Add a random five-bit value, then conditionally mirror/sign-adjust it using
00D54C  1               ; the value at $4C.
00D54C  1               ; ----------------------------------------------------------------------------
00D54C  1               
00D54C  1  20 F5 E5         jsr AdvanceRandomState                   ; $D54C: 20 F5 E5
00D54F  1  29 1F            and #$1F                    ; $D54F: 29 1F
00D551  1               
00D551  1  65 90            adc RandomVerticalMotion          ; $D551: 65 90
00D553  1  45 4C            eor HorizontalDirectionMask           ; $D553: 45 4C
00D555  1  85 90            sta RandomVerticalMotion          ; $D555: 85 90
00D557  1               
00D557  1               ; ----------------------------------------------------------------------------
00D557  1               ; Run the signed math helper again.
00D557  1               ;
00D557  1               ; X is cleared, A contains $90, and Y remains the result from the previous
00D557  1               ; $E855 call.
00D557  1               ; ----------------------------------------------------------------------------
00D557  1               
00D557  1  A2 00            ldx #$00                    ; $D557: A2 00
00D559  1               
00D559  1  20 55 E8         jsr CalculateVectorFromRotatedMask                   ; $D559: 20 55 E8
00D55C  1  AA               tax                         ; $D55C: AA
00D55D  1                                               ; Preserve the second result in X.
00D55D  1               
00D55D  1  68               pla                         ; $D55D: 68
00D55E  1                                               ; Restore the first result in A.
00D55E  1               
00D55E  1  20 2A CA         jsr InitializeBaseMotion            ; $D55E: 20 2A CA
00D561  1               
00D561  1               ; ============================================================================
00D561  1               ; $D561-$D57A
00D561  1               ; Configure transition state, process event slot four, wait for a frame,
00D561  1               ; and dispatch two inline command records.
00D561  1               ; ============================================================================
00D561  1               
00D561  1  C6 86            dec TrajectoryEvaluationEnabled                 ; $D561: C6 86
00D563  1               
00D563  1  A9 10            lda #$10                    ; $D563: A9 10
00D565  1  85 FE            sta PendingAudioFlags             ; $D565: 85 FE
00D567  1               
00D567  1               ; ----------------------------------------------------------------------------
00D567  1               ; Process event slot four.
00D567  1               ; ----------------------------------------------------------------------------
00D567  1               
00D567  1  A0 04            ldy #$04                    ; $D567: A0 04
00D569  1  20 66 EB         jsr DispatchNextQueuedEvent                   ; $D569: 20 66 EB
00D56C  1               
00D56C  1               ; ----------------------------------------------------------------------------
00D56C  1               ; Synchronize with the frame/update system.
00D56C  1               ; ----------------------------------------------------------------------------
00D56C  1               
00D56C  1  20 48 EB         jsr SelectObjectEventBank1                   ; $D56C: 20 48 EB
00D56F  1               
00D56F  1               ; ----------------------------------------------------------------------------
00D56F  1               ; Dispatch the first inline command record.
00D56F  1               ; ----------------------------------------------------------------------------
00D56F  1               
00D56F  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $D56F: 20 0A EB
00D572  1               
00D572  1  25 30 DC         .byte $25,$30,$DC           ; $D572-$D574
00D575  1               
00D575  1               ; ----------------------------------------------------------------------------
00D575  1               ; Dispatch the second inline command record.
00D575  1               ; ----------------------------------------------------------------------------
00D575  1               
00D575  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $D575: 20 0A EB
00D578  1               
00D578  1  29 4C CB         .byte $29,$4C,$CB           ; $D578-$D57A
00D57B  1               
00D57B  1               ; ============================================================================
00D57B  1               ; $D57B-$D598
00D57B  1               ; Short delay followed by an animation loop.
00D57B  1               ; ============================================================================
00D57B  1               
00D57B  1  A9 02            lda #$02                    ; $D57B: A9 02
00D57D  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $D57D: 20 41 EB
00D580  1               
00D580  1  A9 40            lda #$40                    ; $D580: A9 40
00D582  1  85 FE            sta PendingAudioFlags             ; $D582: 85 FE
00D584  1               
00D584  1               ; ----------------------------------------------------------------------------
00D584  1               ; If the current animation value is already five or greater, skip the loop
00D584  1               ; and continue at $D599.
00D584  1               ; ----------------------------------------------------------------------------
00D584  1               
00D584  1               UpdateMotionEndAnimation:    ; $D584
00D584  1  AD B3 03         lda $03B3                   ; $D584: AD B3 03
00D587  1  C9 05            cmp #$05                    ; $D587: C9 05
00D589  1  B0 0E            bcs FinishRandomMotionSequence
00D58B  1                                               ; $D589: B0 0E
00D58B  1               
00D58B  1               ; ----------------------------------------------------------------------------
00D58B  1               ; Increment the animation value, wait eight ticks, and reduce $8D by two.
00D58B  1               ;
00D58B  1               ; Continue while the second decrement leaves $8D nonnegative.
00D58B  1               ; ----------------------------------------------------------------------------
00D58B  1               
00D58B  1  EE B3 03         inc $03B3                   ; $D58B: EE B3 03
00D58E  1               
00D58E  1  A9 08            lda #$08                    ; $D58E: A9 08
00D590  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $D590: 20 41 EB
00D593  1               
00D593  1  C6 8D            dec FielderInputBalance       ; $D593: C6 8D
00D595  1  C6 8D            dec FielderInputBalance       ; $D595: C6 8D
00D597  1               
00D597  1  10 EB            bpl UpdateMotionEndAnimation
00D599  1                                               ; $D597: 10 EB
00D599  1               ; ============================================================================
00D599  1               ; $D599-$D5B8
00D599  1               ; Process two event slots, dispatch two inline commands, wait, advance state,
00D599  1               ; and leave through the common engine exit.
00D599  1               ; ============================================================================
00D599  1               
00D599  1               FinishRandomMotionSequence:     ; $D599
00D599  1  A0 13            ldy #$13                    ; $D599: A0 13
00D59B  1  20 66 EB         jsr DispatchNextQueuedEvent                   ; $D59B: 20 66 EB
00D59E  1               
00D59E  1  A0 0F            ldy #$0F                    ; $D59E: A0 0F
00D5A0  1  20 66 EB         jsr DispatchNextQueuedEvent                   ; $D5A0: 20 66 EB
00D5A3  1               
00D5A3  1               ; ----------------------------------------------------------------------------
00D5A3  1               ; Dispatch the first inline command record.
00D5A3  1               ; ----------------------------------------------------------------------------
00D5A3  1               
00D5A3  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $D5A3: 20 0A EB
00D5A6  1               
00D5A6  1  06 ED D9         .byte $06,$ED,$D9           ; $D5A6-$D5A8
00D5A9  1               
00D5A9  1               ; ----------------------------------------------------------------------------
00D5A9  1               ; Dispatch the second inline command record.
00D5A9  1               ; ----------------------------------------------------------------------------
00D5A9  1               
00D5A9  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $D5A9: 20 0A EB
00D5AC  1               
00D5AC  1  11 D7 D5         .byte $11,$D7,$D5           ; $D5AC-$D5AE
00D5AF  1               
00D5AF  1               ; ----------------------------------------------------------------------------
00D5AF  1               ; Wait $3C ticks, advance $A2, and leave through the common exit.
00D5AF  1               ; ----------------------------------------------------------------------------
00D5AF  1               
00D5AF  1  A9 3C            lda #$3C                    ; $D5AF: A9 3C
00D5B1  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $D5B1: 20 41 EB
00D5B4  1               
00D5B4  1  E6 A2            inc ObjectSequenceState           ; $D5B4: E6 A2
00D5B6  1               
00D5B6  1  4C 6A EB         jmp CommonEngineExit                   ; $D5B6: 4C 6A EB
00D5B9  1               
00D5B9  1               ; ============================================================================
00D5B9  1               ; $D5B9-$D5D7
00D5B9  1               ; Lookup data used by SelectRandomMotionParameters.
00D5B9  1               ;
00D5B9  1               ; Several instructions intentionally use base addresses immediately before
00D5B9  1               ; these tables. The labels below reflect the actual bytes, while the code
00D5B9  1               ; continues to use the original literal operand addresses:
00D5B9  1               ;
00D5B9  1               ;   ADC $D5B8,X
00D5B9  1               ;   CMP $D5BD,X
00D5B9  1               ;   ADC $D5C3,X
00D5B9  1               ;   CMP $D5CE,X
00D5B9  1               ; ============================================================================
00D5B9  1               
00D5B9  1               ; ----------------------------------------------------------------------------
00D5B9  1               ; $D5B9-$D5BD
00D5B9  1               ; Five randomized base values.
00D5B9  1               ;
00D5B9  1               ; Accessed through:
00D5B9  1               ;
00D5B9  1               ;   ADC $D5B8,X
00D5B9  1               ;
00D5B9  1               ; Expected X values are $01-$05:
00D5B9  1               ;
00D5B9  1               ;   X=$01 -> $D5B9 = $C0
00D5B9  1               ;   X=$02 -> $D5BA = $E0
00D5B9  1               ;   X=$03 -> $D5BB = $00
00D5B9  1               ;   X=$04 -> $D5BC = $40
00D5B9  1               ;   X=$05 -> $D5BD = $60
00D5B9  1               ; ----------------------------------------------------------------------------
00D5B9  1               
00D5B9  1               RandomMotionBaseTable:                     ; $D5B9
00D5B9  1  C0 E0 00 40      .byte $C0,$E0,$00,$40,$60
00D5BD  1  60           
00D5BE  1               
00D5BE  1               ; ----------------------------------------------------------------------------
00D5BE  1               ; $D5BE-$D5C2
00D5BE  1               ; Five threshold values.
00D5BE  1               ;
00D5BE  1               ; Accessed through:
00D5BE  1               ;
00D5BE  1               ;   CMP $D5BD,X
00D5BE  1               ;
00D5BE  1               ; Expected X values are $01-$05:
00D5BE  1               ;
00D5BE  1               ;   X=$01 -> $D5BE = $00
00D5BE  1               ;   X=$02 -> $D5BF = $4B
00D5BE  1               ;   X=$03 -> $D5C0 = $85
00D5BE  1               ;   X=$04 -> $D5C1 = $BC
00D5BE  1               ;   X=$05 -> $D5C2 = $F0
00D5BE  1               ; ----------------------------------------------------------------------------
00D5BE  1               
00D5BE  1               RandomMotionThresholdTable:                     ; $D5BE
00D5BE  1  00 4B 85 BC      .byte $00,$4B,$85,$BC,$F0
00D5C2  1  F0           
00D5C3  1               
00D5C3  1               ; ----------------------------------------------------------------------------
00D5C3  1               ; $D5C3-$D5CC
00D5C3  1               ; Ten offset/result values.
00D5C3  1               ;
00D5C3  1               ; Accessed directly through:
00D5C3  1               ;
00D5C3  1               ;   ADC $D5C3,X
00D5C3  1               ; ----------------------------------------------------------------------------
00D5C3  1               
00D5C3  1               RandomMotionAngleTable:                     ; $D5C3
00D5C3  1  01 06 09 0C      .byte $01,$06,$09,$0C,$12
00D5C7  1  12           
00D5C8  1  16 18 1C 1E      .byte $16,$18,$1C,$1E,$20
00D5CC  1  20           
00D5CD  1               
00D5CD  1               ; ----------------------------------------------------------------------------
00D5CD  1               ; $D5CD
00D5CD  1               ; Standalone value immediately before the next threshold table.
00D5CD  1               ;
00D5CD  1               ; Its use is not yet confirmed during the first pass.
00D5CD  1               ; ----------------------------------------------------------------------------
00D5CD  1               
00D5CD  1               RandomMotionAnglePadding:                      ; $D5CD
00D5CD  1  02               .byte $02
00D5CE  1               
00D5CE  1               ; ----------------------------------------------------------------------------
00D5CE  1               ; $D5CE-$D5D7
00D5CE  1               ; Ten threshold values.
00D5CE  1               ;
00D5CE  1               ; Accessed through:
00D5CE  1               ;
00D5CE  1               ;   CMP $D5CE,X
00D5CE  1               ;
00D5CE  1               ; The search starts with X=$0A and decrements X before comparing, so the first
00D5CE  1               ; access uses X=$09 and reads $D5D7.
00D5CE  1               ; ----------------------------------------------------------------------------
00D5CE  1               
00D5CE  1               RandomMotionAngleThresholdTable:                     ; $D5CE
00D5CE  1  00 0A 19 37      .byte $00,$0A,$19,$37,$55
00D5D2  1  55           
00D5D3  1  87 B9 DC EB      .byte $87,$B9,$DC,$EB,$F5
00D5D7  1  F5           
00D5D8  1               
00D5D8  1               ; ============================================================================
00D5D8  1               ; $D5D8-$D60F
00D5D8  1               ; Wait for a group of state and movement fields to clear.
00D5D8  1               ;
00D5D8  1               ; The routine initializes a $3C-frame countdown in $76. While any monitored
00D5D8  1               ; field remains nonzero, the countdown is reset to $3C. Once every field is
00D5D8  1               ; zero, $76 counts down to zero.
00D5D8  1               ; ============================================================================
00D5D8  1               
00D5D8  1               WaitForMotionToSettle:          ; $D5D8
00D5D8  1  A9 3C            lda #$3C                    ; $D5D8: A9 3C
00D5DA  1  85 76            sta MotionSettledCountdown        ; $D5DA: 85 76
00D5DC  1               
00D5DC  1               ; ----------------------------------------------------------------------------
00D5DC  1               ; Wait for the next frame/update.
00D5DC  1               ; ----------------------------------------------------------------------------
00D5DC  1               
00D5DC  1               Routine_D5DC_WaitFrame:         ; $D5DC
00D5DC  1  20 48 EB         jsr SelectObjectEventBank1                   ; $D5DC: 20 48 EB
00D5DF  1               
00D5DF  1               ; ----------------------------------------------------------------------------
00D5DF  1               ; Combine the monitored state fields.
00D5DF  1               ;
00D5DF  1               ; Any nonzero field restarts the routine at $D5D8, resetting the countdown.
00D5DF  1               ; ----------------------------------------------------------------------------
00D5DF  1               
00D5DF  1  A5 6F            lda PendingEvent            ; $D5DF: A5 6F
00D5E1  1               
00D5E1  1  0D 73 05         ora $0573                   ; $D5E1: 0D 73 05
00D5E4  1  0D 74 05         ora $0574                   ; $D5E4: 0D 74 05
00D5E7  1  0D 75 05         ora $0575                   ; $D5E7: 0D 75 05
00D5EA  1  0D 76 05         ora $0576                   ; $D5EA: 0D 76 05
00D5ED  1  0D 77 05         ora $0577                   ; $D5ED: 0D 77 05
00D5F0  1  0D 78 05         ora $0578                   ; $D5F0: 0D 78 05
00D5F3  1  0D 79 05         ora $0579                   ; $D5F3: 0D 79 05
00D5F6  1  0D 7A 05         ora $057A                   ; $D5F6: 0D 7A 05
00D5F9  1               
00D5F9  1  0D 08 05         ora $0508                   ; $D5F9: 0D 08 05
00D5FC  1  0D 39 05         ora $0539                   ; $D5FC: 0D 39 05
00D5FF  1  0D 6A 05         ora $056A                   ; $D5FF: 0D 6A 05
00D602  1               
00D602  1  D0 D4            bne WaitForMotionToSettle   ; $D602: D0 D4
00D604  1               
00D604  1               ; ----------------------------------------------------------------------------
00D604  1               ; All monitored values are zero. Count down $76 while continuing to wait for
00D604  1               ; frames and recheck every field.
00D604  1               ; ----------------------------------------------------------------------------
00D604  1               
00D604  1  C6 76            dec MotionSettledCountdown        ; $D604: C6 76
00D606  1  D0 D4            bne Routine_D5DC_WaitFrame  ; $D606: D0 D4
00D608  1               
00D608  1               ; ----------------------------------------------------------------------------
00D608  1               ; Process command $08 and leave through the common engine exit.
00D608  1               ; ----------------------------------------------------------------------------
00D608  1               
00D608  1  A2 08            ldx #$08                    ; $D608: A2 08
00D60A  1  20 2A EB         jsr ProcessQueuedObjectEvent                   ; $D60A: 20 2A EB
00D60D  1               
00D60D  1  4C 6A EB         jmp CommonEngineExit                   ; $D60D: 4C 6A EB
00D610  1               
00D610  1               ; ============================================================================
00D610  1               ; $D610-$D65D
00D610  1               ; Initialize animation values, create three indexed object records, and select
00D610  1               ; an additional record according to the active object-state entries.
00D610  1               ; ============================================================================
00D610  1               
00D610  1               ; ----------------------------------------------------------------------------
00D610  1               ; Contract:
00D610  1               ;   Description: Initializes Secondary Actors.
00D610  1               ;   Entry: Registers: A; Memory: $059b, $059a, $0599, $0598
00D610  1               ;   Returns/products: Registers/clobbers: A, X
00D610  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00D610  1               ;   Memory effects: $03b4, $03b5, $03b6, $039f, $03a0, $03a1
00D610  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00D610  1               ;          comparison, load, or store path and are not a stable API product.
00D610  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00D610  1               ; ----------------------------------------------------------------------------
00D610  1               InitializeSecondaryActors:                   ; $D610
00D610  1  A9 7A            lda #$7A                    ; $D610: A9 7A
00D612  1               
00D612  1               ; ----------------------------------------------------------------------------
00D612  1               ; Initialize three animation/state entries in each of two arrays.
00D612  1               ; ----------------------------------------------------------------------------
00D612  1               
00D612  1  8D B4 03         sta $03B4                   ; $D612: 8D B4 03
00D615  1  8D B5 03         sta $03B5                   ; $D615: 8D B5 03
00D618  1  8D B6 03         sta $03B6                   ; $D618: 8D B6 03
00D61B  1               
00D61B  1  8D 9F 03         sta $039F                   ; $D61B: 8D 9F 03
00D61E  1  8D A0 03         sta $03A0                   ; $D61E: 8D A0 03
00D621  1  8D A1 03         sta $03A1                   ; $D621: 8D A1 03
00D624  1               
00D624  1               ; ----------------------------------------------------------------------------
00D624  1               ; Initialize object offset $08.
00D624  1               ;
00D624  1               ; Routine $C9A7 consumes five inline bytes:
00D624  1               ;
00D624  1               ;   $08                 object offset/metadata
00D624  1               ;   $00,$04,$00,$F6     four field values
00D624  1               ; ----------------------------------------------------------------------------
00D624  1               
00D624  1  20 A7 C9         jsr LoadObjectPositionInline
00D627  1                                               ; $D624: 20 A7 C9
00D627  1               
00D627  1  08               .byte $08                   ; $D627
00D628  1  00 04 00 F6      .byte $00,$04,$00,$F6       ; $D628-$D62B
00D62C  1               
00D62C  1               ; ----------------------------------------------------------------------------
00D62C  1               ; Initialize object offset $0A.
00D62C  1               ; ----------------------------------------------------------------------------
00D62C  1               
00D62C  1  20 A7 C9         jsr LoadObjectPositionInline
00D62F  1                                               ; $D62C: 20 A7 C9
00D62F  1               
00D62F  1  0A               .byte $0A                   ; $D62F
00D630  1  00 05 00 F6      .byte $00,$05,$00,$F6       ; $D630-$D633
00D634  1               
00D634  1               ; ----------------------------------------------------------------------------
00D634  1               ; Initialize object offset $0C.
00D634  1               ; ----------------------------------------------------------------------------
00D634  1               
00D634  1  20 A7 C9         jsr LoadObjectPositionInline
00D637  1                                               ; $D634: 20 A7 C9
00D637  1               
00D637  1  0C               .byte $0C                   ; $D637
00D638  1  00 06 00 F6      .byte $00,$06,$00,$F6       ; $D638-$D63B
00D63C  1               
00D63C  1               ; ----------------------------------------------------------------------------
00D63C  1               ; Search the object-state entries $059B through $0598 for value $06.
00D63C  1               ;
00D63C  1               ; If any entry contains $06, execution continues at $D656. Otherwise, A is
00D63C  1               ; changed to $FF and execution branches forward to $D66A.
00D63C  1               ; ----------------------------------------------------------------------------
00D63C  1               
00D63C  1  A9 06            lda #$06                    ; $D63C: A9 06
00D63E  1               
00D63E  1  CD 9B 05         cmp $059B                   ; $D63E: CD 9B 05
00D641  1  F0 13            beq InitializeState6Actor
00D643  1                                               ; $D641: F0 13
00D643  1               
00D643  1  CD 9A 05         cmp $059A                   ; $D643: CD 9A 05
00D646  1  F0 0E            beq InitializeState6Actor
00D648  1                                               ; $D646: F0 0E
00D648  1               
00D648  1  CD 99 05         cmp $0599                   ; $D648: CD 99 05
00D64B  1  F0 09            beq InitializeState6Actor
00D64D  1                                               ; $D64B: F0 09
00D64D  1               
00D64D  1  CD 98 05         cmp $0598                   ; $D64D: CD 98 05
00D650  1  F0 04            beq InitializeState6Actor
00D652  1                                               ; $D650: F0 04
00D652  1               
00D652  1  A9 FF            lda #$FF                    ; $D652: A9 FF
00D654  1  D0 14            bne StoreState6Actor            ; $D654: D0 14
00D656  1                                               ; Always taken because A is nonzero.
00D656  1               
00D656  1               ; ----------------------------------------------------------------------------
00D656  1               ; Initialize object offset $0C with an alternate field set when state $06 was
00D656  1               ; found in one of the four object-state entries.
00D656  1               ; ----------------------------------------------------------------------------
00D656  1               
00D656  1               InitializeState6Actor: ; $D656
00D656  1  20 A7 C9         jsr LoadObjectPositionInline
00D659  1                                               ; $D656: 20 A7 C9
00D659  1               
00D659  1  0C               .byte $0C                   ; $D659
00D65A  1  80 F8 80 00      .byte $80,$F8,$80,$00       ; $D65A-$D65D
00D65E  1               
00D65E  1               ; ============================================================================
00D65E  1               ; $D65E-$D69A
00D65E  1               ; Configure object $0C, search active object-state entries for value $04,
00D65E  1               ; optionally initialize object $0A, and update animation values.
00D65E  1               ; ============================================================================
00D65E  1               
00D65E  1  A9 1A            lda #$1A                    ; $D65E: A9 1A
00D660  1  8D B6 03         sta $03B6                   ; $D660: 8D B6 03
00D663  1               
00D663  1  A9 4F            lda #$4F                    ; $D663: A9 4F
00D665  1  8D A1 03         sta $03A1                   ; $D665: 8D A1 03
00D668  1               
00D668  1               ; ----------------------------------------------------------------------------
00D668  1               ; Set object-state entry $059B and zero-page working state $A1 to $06.
00D668  1               ; ----------------------------------------------------------------------------
00D668  1               
00D668  1  A9 06            lda #$06                    ; $D668: A9 06
00D66A  1               
00D66A  1               StoreState6Actor:                   ; $D66A
00D66A  1  8D 9B 05         sta $059B                   ; $D66A: 8D 9B 05
00D66D  1  85 A1            sta SecondaryActorState2      ; $D66D: 85 A1
00D66F  1               
00D66F  1               ; ----------------------------------------------------------------------------
00D66F  1               ; Update object offset $0C.
00D66F  1               ; ----------------------------------------------------------------------------
00D66F  1               
00D66F  1  A2 0C            ldx #$0C                    ; $D66F: A2 0C
00D671  1  20 B7 E6         jsr ClearMovementTransforms                   ; $D671: 20 B7 E6
00D674  1               
00D674  1               ; ----------------------------------------------------------------------------
00D674  1               ; Search state entries $059A-$0598 for value $04.
00D674  1               ;
00D674  1               ; If no entry contains $04, A becomes $FF and execution branches to $D69D.
00D674  1               ; That branch intentionally skips the LDA #$04 at $D69B while entering the
00D674  1               ; following STA instruction.
00D674  1               ; ----------------------------------------------------------------------------
00D674  1               
00D674  1  A9 04            lda #$04                    ; $D674: A9 04
00D676  1               
00D676  1  CD 9A 05         cmp $059A                   ; $D676: CD 9A 05
00D679  1  F0 0E            beq InitializeState4Actor
00D67B  1                                               ; $D679: F0 0E
00D67B  1               
00D67B  1  CD 99 05         cmp $0599                   ; $D67B: CD 99 05
00D67E  1  F0 09            beq InitializeState4Actor
00D680  1                                               ; $D67E: F0 09
00D680  1               
00D680  1  CD 98 05         cmp $0598                   ; $D680: CD 98 05
00D683  1  F0 04            beq InitializeState4Actor
00D685  1                                               ; $D683: F0 04
00D685  1               
00D685  1  A9 FF            lda #$FF                    ; $D685: A9 FF
00D687  1  D0 14            bne StoreState4Actor ; $D687: D0 14
00D689  1                                               ; Always taken because A is nonzero.
00D689  1               
00D689  1               ; ----------------------------------------------------------------------------
00D689  1               ; Initialize object offset $0A when state $04 was found.
00D689  1               ;
00D689  1               ; Routine $C9A7 consumes five inline bytes:
00D689  1               ;
00D689  1               ;   $0A                 object offset/metadata
00D689  1               ;   $00,$FF,$00,$08     four field values
00D689  1               ; ----------------------------------------------------------------------------
00D689  1               
00D689  1               InitializeState4Actor:  ; $D689
00D689  1  20 A7 C9         jsr LoadObjectPositionInline
00D68C  1                                               ; $D689: 20 A7 C9
00D68C  1               
00D68C  1  0A               .byte $0A                   ; $D68C
00D68D  1  00 FF 00 08      .byte $00,$FF,$00,$08       ; $D68D-$D690
00D691  1               
00D691  1               ; ----------------------------------------------------------------------------
00D691  1               ; Update the corresponding animation values.
00D691  1               ; ----------------------------------------------------------------------------
00D691  1               
00D691  1  A9 1D            lda #$1D                    ; $D691: A9 1D
00D693  1  8D B5 03         sta $03B5                   ; $D693: 8D B5 03
00D696  1               
00D696  1  A9 55            lda #$55                    ; $D696: A9 55
00D698  1  8D A0 03         sta $03A0                   ; $D698: 8D A0 03
00D69B  1               ; ============================================================================
00D69B  1               ; $D69B-$D6DA
00D69B  1               ; Configure object $0A, search for state $02, optionally initialize object
00D69B  1               ; $08, configure its animation fields, and clear $0598.
00D69B  1               ; ============================================================================
00D69B  1               
00D69B  1  A9 04            lda #$04                    ; $D69B: A9 04
00D69D  1               
00D69D  1               ; ----------------------------------------------------------------------------
00D69D  1               ; Shared entry from the earlier state search.
00D69D  1               ;
00D69D  1               ; Normal flow stores $04. The branch from $D687 enters here with A = $FF.
00D69D  1               ; ----------------------------------------------------------------------------
00D69D  1               
00D69D  1               StoreState4Actor:        ; $D69D
00D69D  1  8D 9A 05         sta $059A                   ; $D69D: 8D 9A 05
00D6A0  1  85 A0            sta SecondaryActorState1      ; $D6A0: 85 A0
00D6A2  1               
00D6A2  1               ; ----------------------------------------------------------------------------
00D6A2  1               ; Update object offset $0A.
00D6A2  1               ; ----------------------------------------------------------------------------
00D6A2  1               
00D6A2  1  A2 0A            ldx #$0A                    ; $D6A2: A2 0A
00D6A4  1  20 B7 E6         jsr ClearMovementTransforms                   ; $D6A4: 20 B7 E6
00D6A7  1               
00D6A7  1               ; ----------------------------------------------------------------------------
00D6A7  1               ; Search state entries $0599 and $0598 for value $02.
00D6A7  1               ;
00D6A7  1               ; If neither entry contains $02, A becomes $FF and execution enters the shared
00D6A7  1               ; store at $D6CB.
00D6A7  1               ; ----------------------------------------------------------------------------
00D6A7  1               
00D6A7  1  A9 02            lda #$02                    ; $D6A7: A9 02
00D6A9  1               
00D6A9  1  CD 99 05         cmp $0599                   ; $D6A9: CD 99 05
00D6AC  1  F0 09            beq InitializeState2Actor
00D6AE  1                                               ; $D6AC: F0 09
00D6AE  1               
00D6AE  1  CD 98 05         cmp $0598                   ; $D6AE: CD 98 05
00D6B1  1  F0 04            beq InitializeState2Actor
00D6B3  1                                               ; $D6B1: F0 04
00D6B3  1               
00D6B3  1  A9 FF            lda #$FF                    ; $D6B3: A9 FF
00D6B5  1  D0 14            bne StoreState2Actor ; $D6B5: D0 14
00D6B7  1                                               ; Always taken because A is nonzero.
00D6B7  1               
00D6B7  1               ; ----------------------------------------------------------------------------
00D6B7  1               ; Initialize object offset $08 when state $02 was found.
00D6B7  1               ;
00D6B7  1               ; Routine $C9A7 consumes five inline bytes:
00D6B7  1               ;
00D6B7  1               ;   $08                 object offset/metadata
00D6B7  1               ;   $00,$07,$80,$00     four field values
00D6B7  1               ; ----------------------------------------------------------------------------
00D6B7  1               
00D6B7  1               InitializeState2Actor:  ; $D6B7
00D6B7  1  20 A7 C9         jsr LoadObjectPositionInline
00D6BA  1                                               ; $D6B7: 20 A7 C9
00D6BA  1               
00D6BA  1  08               .byte $08                   ; $D6BA
00D6BB  1  00 07 80 00      .byte $00,$07,$80,$00       ; $D6BB-$D6BE
00D6BF  1               
00D6BF  1               ; ----------------------------------------------------------------------------
00D6BF  1               ; Configure the object's animation values.
00D6BF  1               ; ----------------------------------------------------------------------------
00D6BF  1               
00D6BF  1  A9 1D            lda #$1D                    ; $D6BF: A9 1D
00D6C1  1  8D B4 03         sta $03B4                   ; $D6C1: 8D B4 03
00D6C4  1               
00D6C4  1  A9 55            lda #$55                    ; $D6C4: A9 55
00D6C6  1  8D 9F 03         sta $039F                   ; $D6C6: 8D 9F 03
00D6C9  1               
00D6C9  1  A9 02            lda #$02                    ; $D6C9: A9 02
00D6CB  1               
00D6CB  1               ; ----------------------------------------------------------------------------
00D6CB  1               ; Shared store.
00D6CB  1               ;
00D6CB  1               ; Normal flow stores $02. The branch from $D6B5 enters with A = $FF.
00D6CB  1               ; ----------------------------------------------------------------------------
00D6CB  1               
00D6CB  1               StoreState2Actor:        ; $D6CB
00D6CB  1  8D 99 05         sta $0599                   ; $D6CB: 8D 99 05
00D6CE  1  85 9F            sta SecondaryActorState0      ; $D6CE: 85 9F
00D6D0  1               
00D6D0  1               ; ----------------------------------------------------------------------------
00D6D0  1               ; Update object offset $08.
00D6D0  1               ; ----------------------------------------------------------------------------
00D6D0  1               
00D6D0  1  A2 08            ldx #$08                    ; $D6D0: A2 08
00D6D2  1  20 B7 E6         jsr ClearMovementTransforms                   ; $D6D2: 20 B7 E6
00D6D5  1               
00D6D5  1               ; ----------------------------------------------------------------------------
00D6D5  1               ; Clear the first state entry and return.
00D6D5  1               ; ----------------------------------------------------------------------------
00D6D5  1               
00D6D5  1  A9 00            lda #$00                    ; $D6D5: A9 00
00D6D7  1  8D 98 05         sta $0598                   ; $D6D7: 8D 98 05
00D6DA  1               
00D6DA  1  60               rts                         ; $D6DA: 60
00D6DB  1               
00D6DB  1               ; ============================================================================
00D6DB  1               ; $D6DB-$D6F8
00D6DB  1               ; Initial delay and frame-loop setup.
00D6DB  1               ; ============================================================================
00D6DB  1               
00D6DB  1               RunObjectApproachSequence:                   ; $D6DB
00D6DB  1  A9 1E            lda #$1E                    ; $D6DB: A9 1E
00D6DD  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $D6DD: 20 41 EB
00D6E0  1               
00D6E0  1               ; ----------------------------------------------------------------------------
00D6E0  1               ; Clear state $82 and initialize countdown $78 to $1E.
00D6E0  1               ; ----------------------------------------------------------------------------
00D6E0  1               
00D6E0  1  A9 00            lda #$00                    ; $D6E0: A9 00
00D6E2  1  85 82            sta ActorActionComplete                 ; $D6E2: 85 82
00D6E4  1               ResetObjectApproachTimer:
00D6E4  1  A9 1E            lda #$1E                    ; $D6E4: A9 1E
00D6E6  1  85 78            sta StateTimer78            ; $D6E6: 85 78
00D6E8  1               
00D6E8  1               ; ----------------------------------------------------------------------------
00D6E8  1               ; Decrement the countdown and wait for a frame.
00D6E8  1               ; ----------------------------------------------------------------------------
00D6E8  1               
00D6E8  1               UpdateObjectApproachTimer:         ; $D6E8
00D6E8  1  C6 78            dec StateTimer78            ; $D6E8: C6 78
00D6EA  1               UpdateObjectApproachFrame:
00D6EA  1  20 48 EB         jsr SelectObjectEventBank1                   ; $D6EA: 20 48 EB
00D6ED  1               
00D6ED  1               ; ----------------------------------------------------------------------------
00D6ED  1               ; Increment $83 while $8C is below nine.
00D6ED  1               ; ----------------------------------------------------------------------------
00D6ED  1               
00D6ED  1  A5 8C            lda FielderAnimationCountdown      ; $D6ED: A5 8C
00D6EF  1  C9 09            cmp #$09                    ; $D6EF: C9 09
00D6F1  1  B0 02            bcs CheckObjectApproachState ; $D6F1: B0 02
00D6F3  1               
00D6F3  1  E6 83            inc ObjectApproachCount                 ; $D6F3: E6 83
00D6F5  1               
00D6F5  1               ; ----------------------------------------------------------------------------
00D6F5  1               ; If state $82 is nonzero, branch forward to $D745.
00D6F5  1               ; ----------------------------------------------------------------------------
00D6F5  1               
00D6F5  1               CheckObjectApproachState:        ; $D6F5
00D6F5  1  A5 82            lda ActorActionComplete                 ; $D6F5: A5 82
00D6F7  1  D0 4C            bne EvaluateObjectApproachCompletion            ; $D6F7: D0 4C
00D6F9  1               
00D6F9  1               ; ============================================================================
00D6F9  1               ; $D6F9-$D744
00D6F9  1               ; Compare base and object-six coordinates, update $87 when horizontal
00D6F9  1               ; separation exceeds a threshold, and derive a flag in $84.
00D6F9  1               ; ============================================================================
00D6F9  1               
00D6F9  1  AC 3A 05         ldy $053A                   ; $D6F9: AC 3A 05
00D6FC  1  AD 3B 05         lda $053B                   ; $D6FC: AD 3B 05
00D6FF  1               
00D6FF  1               ; ----------------------------------------------------------------------------
00D6FF  1               ; Subtract object-six's vertical coordinate from the base coordinate.
00D6FF  1               ;
00D6FF  1               ; Low bytes:
00D6FF  1               ;   $053A - $0540
00D6FF  1               ;
00D6FF  1               ; High bytes:
00D6FF  1               ;   $053B - $0541
00D6FF  1               ; ----------------------------------------------------------------------------
00D6FF  1               
00D6FF  1  CC 40 05         cpy $0540                   ; $D6FF: CC 40 05
00D702  1  ED 41 05         sbc $0541                   ; $D702: ED 41 05
00D705  1               
00D705  1  C9 00            cmp #$00                    ; $D705: C9 00
00D707  1  10 2D            bpl UpdateObjectCoordinateFlag
00D709  1                                               ; $D707: 10 2D
00D709  1               
00D709  1               ; ----------------------------------------------------------------------------
00D709  1               ; Perform the distance check only while $8C is below nine.
00D709  1               ; ----------------------------------------------------------------------------
00D709  1               
00D709  1  A5 8C            lda FielderAnimationCountdown      ; $D709: A5 8C
00D70B  1  C9 09            cmp #$09                    ; $D70B: C9 09
00D70D  1  B0 23            bcs AddDoubleObjectProximityCount
00D70F  1                                               ; $D70D: B0 23
00D70F  1               
00D70F  1               ; ----------------------------------------------------------------------------
00D70F  1               ; Calculate the horizontal difference:
00D70F  1               ;
00D70F  1               ;   ($0509/$050A) - ($050F/$0510)
00D70F  1               ;
00D70F  1               ; Each result byte is XORed with $4C.
00D70F  1               ; ----------------------------------------------------------------------------
00D70F  1               
00D70F  1  38               sec                         ; $D70F: 38
00D710  1               
00D710  1  AD 09 05         lda $0509                   ; $D710: AD 09 05
00D713  1  ED 0F 05         sbc $050F                   ; $D713: ED 0F 05
00D716  1  45 4C            eor HorizontalDirectionMask          ; $D716: 45 4C
00D718  1  A8               tay                         ; $D718: A8
00D719  1               
00D719  1  AD 0A 05         lda $050A                   ; $D719: AD 0A 05
00D71C  1  ED 10 05         sbc $0510                   ; $D71C: ED 10 05
00D71F  1  45 4C            eor HorizontalDirectionMask           ; $D71F: 45 4C
00D721  1  AA               tax                         ; $D721: AA
00D722  1               
00D722  1               ; ----------------------------------------------------------------------------
00D722  1               ; Subtract $0180 from the signed 16-bit difference in X:Y.
00D722  1               ; ----------------------------------------------------------------------------
00D722  1               
00D722  1  38               sec                         ; $D722: 38
00D723  1               
00D723  1  98               tya                         ; $D723: 98
00D724  1  E9 80            sbc #$80                    ; $D724: E9 80
00D726  1  A8               tay                         ; $D726: A8
00D727  1               
00D727  1  8A               txa                         ; $D727: 8A
00D728  1  E9 00            sbc #$00                    ; $D728: E9 00
00D72A  1  AA               tax                         ; $D72A: AA
00D72B  1               
00D72B  1               ; ----------------------------------------------------------------------------
00D72B  1               ; Compare the adjusted value against $0110.
00D72B  1               ;
00D72B  1               ; Carry is established by CPY #$10 and used by SBC #$01.
00D72B  1               ; If the value is below the threshold, skip the first increment of $87.
00D72B  1               ; ----------------------------------------------------------------------------
00D72B  1               
00D72B  1  C0 10            cpy #$10                    ; $D72B: C0 10
00D72D  1               
00D72D  1  8A               txa                         ; $D72D: 8A
00D72E  1  E9 01            sbc #$01                    ; $D72E: E9 01
00D730  1  90 02            bcc AddObjectProximityCount
00D732  1                                               ; $D730: 90 02
00D732  1               
00D732  1               AddDoubleObjectProximityCount:       ; $D732
00D732  1  E6 87            inc ObjectProximityState                 ; $D732: E6 87
00D734  1               
00D734  1               AddObjectProximityCount:       ; $D734
00D734  1  E6 87            inc ObjectProximityState                 ; $D734: E6 87
00D736  1               
00D736  1               ; ----------------------------------------------------------------------------
00D736  1               ; Normalize the base horizontal coordinate and derive a flag in $84.
00D736  1               ; ----------------------------------------------------------------------------
00D736  1               
00D736  1               UpdateObjectCoordinateFlag:   ; $D736
00D736  1  AC 09 05         ldy $0509                   ; $D736: AC 09 05
00D739  1  AD 0A 05         lda $050A                   ; $D739: AD 0A 05
00D73C  1               
00D73C  1  20 CB E7         jsr AbsoluteValueAY                   ; $D73C: 20 CB E7
00D73F  1               
00D73F  1  C0 60            cpy #$60                    ; $D73F: C0 60
00D741  1  E9 00            sbc #$00                    ; $D741: E9 00
00D743  1               
00D743  1  66 84            ror ObjectApproachDirectionFlag          ; $D743: 66 84
00D745  1               
00D745  1               ; ============================================================================
00D745  1               ; $D745-$D768
00D745  1               ; Evaluate countdown and state flags after the coordinate checks.
00D745  1               ; ============================================================================
00D745  1               
00D745  1               EvaluateObjectApproachCompletion:                   ; $D745
00D745  1  A5 82            lda ActorActionComplete                 ; $D745: A5 82
00D747  1  F0 9B            beq ResetObjectApproachTimer   ; $D747: F0 9B
00D749  1               
00D749  1               ; ----------------------------------------------------------------------------
00D749  1               ; Return to the main frame loop while countdown $78 remains nonzero.
00D749  1               ; ----------------------------------------------------------------------------
00D749  1               
00D749  1  A5 78            lda StateTimer78            ; $D749: A5 78
00D74B  1  D0 9B            bne UpdateObjectApproachTimer  ; $D74B: D0 9B
00D74D  1               
00D74D  1               ; ----------------------------------------------------------------------------
00D74D  1               ; Shift $8D right once.
00D74D  1               ;
00D74D  1               ; If the result is nonzero, return to the frame wait at $D6EA.
00D74D  1               ; ----------------------------------------------------------------------------
00D74D  1               
00D74D  1  A5 8D            lda FielderInputBalance       ; $D74D: A5 8D
00D74F  1  4A               lsr                         ; $D74F: 4A
00D750  1  D0 98            bne UpdateObjectApproachFrame  ; $D750: D0 98
00D752  1               
00D752  1               ; ----------------------------------------------------------------------------
00D752  1               ; If $83 is already nonzero, continue at AdvanceObjectApproachState.
00D752  1               ; ----------------------------------------------------------------------------
00D752  1               
00D752  1  A5 83            lda ObjectApproachCount                    ; $D752: A5 83
00D754  1  D0 13            bne AdvanceObjectApproachState ; $D754: D0 13
00D756  1               
00D756  1               ; ----------------------------------------------------------------------------
00D756  1               ; If $84 is nonnegative, continue at AdvanceObjectApproachState.
00D756  1               ; Otherwise, invoke the state-transition helper at $CC01.
00D756  1               ; ----------------------------------------------------------------------------
00D756  1               
00D756  1  A5 84            lda ObjectApproachDirectionFlag             ; $D756: A5 84
00D758  1  10 0F            bpl AdvanceObjectApproachState ; $D758: 10 0F
00D75A  1               
00D75A  1  20 01 CC         jsr AdvancePrimaryStateSequence               ; $D75A: 20 01 CC
00D75D  1               
00D75D  1               ; ----------------------------------------------------------------------------
00D75D  1               ; When $63 equals four, increment $6E and $46.
00D75D  1               ; All other cases continue at $D783.
00D75D  1               ; ----------------------------------------------------------------------------
00D75D  1               
00D75D  1  A5 63            lda TransitionSequenceState                 ; $D75D: A5 63
00D75F  1  C9 04            cmp #$04                    ; $D75F: C9 04
00D761  1  D0 20            bne ExitObjectApproachState ; $D761: D0 20
00D763  1               
00D763  1  E6 6E            inc ObjectTransitionState                 ; $D763: E6 6E
00D765  1  E6 46            inc StateSequenceActive             ; $D765: E6 46
00D767  1               
00D767  1  D0 1A            bne ExitObjectApproachState ; $D767: D0 1A
00D769  1                                               ; Normally unconditional after INC $46.
00D769  1               
00D769  1               ; ============================================================================
00D769  1               ; Temporary external labels referenced by this stride.
00D769  1               ;
00D769  1               ; Remove each alias when its containing block is decoded.
00D769  1               ; ============================================================================
00D769  1               
00D769  1               ; ============================================================================
00D769  1               ; $D769-$D785
00D769  1               ; Advance the dual-state sequence after the monitored object conditions have
00D769  1               ; completed.
00D769  1               ;
00D769  1               ; This path:
00D769  1               ;   1. Advances the $62/$64 state sequence.
00D769  1               ;   2. Checks whether $62 reached state three.
00D769  1               ;   3. If so, activates state flag $46.
00D769  1               ;   4. Waits $1E ticks.
00D769  1               ;   5. Sets animation/frame $03B3 to $7A.
00D769  1               ;   6. Processes event slot $0D.
00D769  1               ;   7. Leaves through the common engine exit.
00D769  1               ; ============================================================================
00D769  1               
00D769  1               AdvanceObjectApproachState:     ; $D769
00D769  1  20 7A CC         jsr AdvanceDualStateSequence
00D76C  1                                               ; $D769: 20 7A CC
00D76C  1               
00D76C  1  A5 62            lda PrimarySequenceState                 ; $D76C: A5 62
00D76E  1  C9 03            cmp #$03                    ; $D76E: C9 03
00D770  1  D0 11            bne ExitObjectApproachState ; $D770: D0 11
00D772  1               
00D772  1               ; ----------------------------------------------------------------------------
00D772  1               ; State $62 reached three.
00D772  1               ; Activate the next state and run a short timed animation.
00D772  1               ; ----------------------------------------------------------------------------
00D772  1               
00D772  1  E6 46            inc StateSequenceActive             ; $D772: E6 46
00D774  1               
00D774  1  A9 1E            lda #$1E                    ; $D774: A9 1E
00D776  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $D776: 20 41 EB
00D779  1               
00D779  1  A9 7A            lda #$7A                    ; $D779: A9 7A
00D77B  1  8D B3 03         sta $03B3                   ; $D77B: 8D B3 03
00D77E  1               
00D77E  1               ; ----------------------------------------------------------------------------
00D77E  1               ; Process event slot $0D.
00D77E  1               ; ----------------------------------------------------------------------------
00D77E  1               
00D77E  1  A0 0D            ldy #$0D                    ; $D77E: A0 0D
00D780  1  20 66 EB         jsr DispatchNextQueuedEvent                   ; $D780: 20 66 EB
00D783  1               
00D783  1               ; ----------------------------------------------------------------------------
00D783  1               ; Common exit.
00D783  1               ;
00D783  1               ; The BNE at $D770 branches directly here.
00D783  1               ; ----------------------------------------------------------------------------
00D783  1               
00D783  1               ExitObjectApproachState:        ; $D783
00D783  1  4C 6A EB         jmp CommonEngineExit                   ; $D783: 4C 6A EB
00D786  1               
00D786  1               ; ============================================================================
00D786  1               ; $D786-$D7AA
00D786  1               ; Wait for the base vertical coordinate to reach $F6, clear motion state,
00D786  1               ; advance the object state, and dispatch two inline commands.
00D786  1               ; ============================================================================
00D786  1               
00D786  1               WaitForVerticalPositionF6:      ; $D786
00D786  1  20 48 EB         jsr SelectObjectEventBank1                   ; $D786: 20 48 EB
00D789  1               
00D789  1  A2 04            ldx #$04                    ; $D789: A2 04
00D78B  1  38               sec                         ; $D78B: 38
00D78C  1               
00D78C  1  AD 3B 05         lda $053B                   ; $D78C: AD 3B 05
00D78F  1  E9 F6            sbc #$F6                    ; $D78F: E9 F6
00D791  1  D0 F3            bne WaitForVerticalPositionF6
00D793  1                                               ; $D791: D0 F3
00D793  1               
00D793  1               ; ----------------------------------------------------------------------------
00D793  1               ; Clear active motion and value state, then advance $82.
00D793  1               ; ----------------------------------------------------------------------------
00D793  1               
00D793  1  85 5C            sta BaseMotionActive            ; $D793: 85 5C
00D795  1                                               ; A is zero after the successful comparison.
00D795  1               
00D795  1  85 81            sta RandomValue81           ; $D795: 85 81
00D797  1               
00D797  1  E6 82            inc ActorActionComplete                 ; $D797: E6 82
00D799  1               
00D799  1  20 E6 E3         jsr InitializeBaseObjectFromCurrent                   ; $D799: 20 E6 E3
00D79C  1               
00D79C  1               ; ----------------------------------------------------------------------------
00D79C  1               ; Dispatch two inline command records.
00D79C  1               ; ----------------------------------------------------------------------------
00D79C  1               
00D79C  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $D79C: 20 0A EB
00D79F  1               
00D79F  1  11 D7 D5         .byte $11,$D7,$D5           ; $D79F-$D7A1
00D7A2  1               
00D7A2  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $D7A2: 20 0A EB
00D7A5  1               
00D7A5  1  1D AA D7         .byte $1D,$AA,$D7           ; $D7A5-$D7A7
00D7A8  1               
00D7A8  1  4C 8B E0         jmp ObjectStateDispatch_NextPath                   ; $D7A8: 4C 8B E0
00D7AB  1               
00D7AB  1               ; ============================================================================
00D7AB  1               ; $D7AB-$D7C9
00D7AB  1               ; Initialize an object timer, wait for four monitored object fields to clear,
00D7AB  1               ; then count the timer down to zero.
00D7AB  1               ;
00D7AB  1               ; Entry:
00D7AB  1               ;   CurrentObjectIndex selects the timer at $05B1,X.
00D7AB  1               ; ============================================================================
00D7AB  1               
00D7AB  1               WaitForObjectFieldsToClear:     ; $D7AB
00D7AB  1  A6 E1            ldx CurrentObjectIndex      ; $D7AB: A6 E1
00D7AD  1               
00D7AD  1  A9 32            lda #$32                    ; $D7AD: A9 32
00D7AF  1  9D B1 05         sta $05B1,x                 ; $D7AF: 9D B1 05
00D7B2  1               
00D7B2  1               WaitForObjectFieldsFrame:       ; $D7B2
00D7B2  1  20 48 EB         jsr SelectObjectEventBank1                   ; $D7B2: 20 48 EB
00D7B5  1               
00D7B5  1  AD 73 05         lda $0573                   ; $D7B5: AD 73 05
00D7B8  1  0D 75 05         ora $0575                   ; $D7B8: 0D 75 05
00D7BB  1  0D 77 05         ora $0577                   ; $D7BB: 0D 77 05
00D7BE  1  0D 79 05         ora $0579                   ; $D7BE: 0D 79 05
00D7C1  1               
00D7C1  1  D0 E8            bne WaitForObjectFieldsToClear
00D7C3  1                                               ; $D7C1: D0 E8
00D7C3  1               
00D7C3  1               ; ----------------------------------------------------------------------------
00D7C3  1               ; Once all monitored fields are zero, count down $05B1,X.
00D7C3  1               ;
00D7C3  1               ; If the countdown remains nonzero, wait for another frame but do not
00D7C3  1               ; reinitialize the timer.
00D7C3  1               ; ----------------------------------------------------------------------------
00D7C3  1               
00D7C3  1  A6 E1            ldx CurrentObjectIndex      ; $D7C3: A6 E1
00D7C5  1               
00D7C5  1  DE B1 05         dec $05B1,x                 ; $D7C5: DE B1 05
00D7C8  1  D0 E8            bne WaitForObjectFieldsFrame
00D7CA  1                                               ; $D7C8: D0 E8
00D7CA  1               
00D7CA  1               ; ============================================================================
00D7CA  1               ; $D7CA-$D800
00D7CA  1               ; Process event slots, initialize animation and movement, wait for a vertical
00D7CA  1               ; position condition, then clear the active action state.
00D7CA  1               ; ============================================================================
00D7CA  1               
00D7CA  1  A0 11            ldy #$11                    ; $D7CA: A0 11
00D7CC  1  20 66 EB         jsr DispatchNextQueuedEvent                   ; $D7CC: 20 66 EB
00D7CF  1               
00D7CF  1  A0 04            ldy #$04                    ; $D7CF: A0 04
00D7D1  1  20 66 EB         jsr DispatchNextQueuedEvent                   ; $D7D1: 20 66 EB
00D7D4  1               
00D7D4  1               ; ----------------------------------------------------------------------------
00D7D4  1               ; Clear the sequence counter and wait $14 ticks.
00D7D4  1               ; ----------------------------------------------------------------------------
00D7D4  1               
00D7D4  1  A9 00            lda #$00                    ; $D7D4: A9 00
00D7D6  1  85 7E            sta ActionSequenceCounter         ; $D7D6: 85 7E
00D7D8  1               
00D7D8  1  A9 14            lda #$14                    ; $D7D8: A9 14
00D7DA  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $D7DA: 20 41 EB
00D7DD  1               
00D7DD  1               ; ----------------------------------------------------------------------------
00D7DD  1               ; Advance animation state and initialize base motion.
00D7DD  1               ; ----------------------------------------------------------------------------
00D7DD  1               
00D7DD  1  EE B2 03         inc $03B2                   ; $D7DD: EE B2 03
00D7E0  1               
00D7E0  1  A9 10            lda #$10                    ; $D7E0: A9 10
00D7E2  1  8D B7 03         sta $03B7                   ; $D7E2: 8D B7 03
00D7E5  1               
00D7E5  1  A2 00            ldx #$00                    ; $D7E5: A2 00
00D7E7  1  A0 20            ldy #$20                    ; $D7E7: A0 20
00D7E9  1               
00D7E9  1  20 23 CA         jsr InitializeBaseMotionZero
00D7EC  1                                               ; $D7E9: 20 23 CA
00D7EC  1               
00D7EC  1               ; ----------------------------------------------------------------------------
00D7EC  1               ; Wait until the signed vertical high byte becomes nonnegative and reaches at
00D7EC  1               ; least $02.
00D7EC  1               ; ----------------------------------------------------------------------------
00D7EC  1               
00D7EC  1               WaitForVerticalPosition02:      ; $D7EC
00D7EC  1  20 48 EB         jsr SelectObjectEventBank1                   ; $D7EC: 20 48 EB
00D7EF  1               
00D7EF  1  AD 3B 05         lda $053B                   ; $D7EF: AD 3B 05
00D7F2  1  C9 02            cmp #$02                    ; $D7F2: C9 02
00D7F4  1  30 F6            bmi WaitForVerticalPosition02
00D7F6  1                                               ; $D7F4: 30 F6
00D7F6  1               
00D7F6  1               ; ----------------------------------------------------------------------------
00D7F6  1               ; Run the helper for object offset $0E, then clear action and motion state.
00D7F6  1               ; ----------------------------------------------------------------------------
00D7F6  1               
00D7F6  1  A2 0E            ldx #$0E                    ; $D7F6: A2 0E
00D7F8  1  20 E8 E3         jsr CopyCurrentObjectPositionToBaseAfterIndex                   ; $D7F8: 20 E8 E3
00D7FB  1               
00D7FB  1  A9 00            lda #$00                    ; $D7FB: A9 00
00D7FD  1  85 9D            sta CurrentActionState             ; $D7FD: 85 9D
00D7FF  1  85 5C            sta BaseMotionActive            ; $D7FF: 85 5C
00D801  1               
00D801  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $D801: 20 0A EB
00D804  1               
00D804  1                   ; Inline command record consumed by QueueInlineObjectEvent.
00D804  1  17 AC D2         .byte $17,$AC,$D2           ; $D804-$D806
00D807  1               
00D807  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $D807: 20 0A EB
00D80A  1               
00D80A  1                   ; Inline command record consumed by QueueInlineObjectEvent.
00D80A  1  11 D7 D5         .byte $11,$D7,$D5           ; $D80A-$D80C
00D80D  1               
00D80D  1  4C 6A EB         jmp CommonEngineExit                   ; $D80D: 4C 6A EB
00D810  1               
00D810  1               ; ============================================================================
00D810  1               ; $D810-$D836
00D810  1               ; Select an animation frame and delay using table-driven state.
00D810  1               ;
00D810  1               ; Entry:
00D810  1               ;   A  = base state or animation index
00D810  1               ;   X  = object/sprite-array index
00D810  1               ;   $CB = additional index offset
00D810  1               ;
00D810  1               ; Operation:
00D810  1               ;   1. Add $CB to A and preserve the resulting table index.
00D810  1               ;   2. Update the object through $E6B7.
00D810  1               ;   3. Depending on carry and the current animation frame, optionally select
00D810  1               ;      a replacement frame from the table at $D837.
00D810  1               ;   4. Load a delay from the table at $D84F.
00D810  1               ;   5. Tail-call the delay helper at $EB41.
00D810  1               ; ============================================================================
00D810  1               
00D810  1               SelectAnimationFrameAndDelay:   ; $D810
00D810  1  18               clc                         ; $D810: 18
00D811  1  65 CB            adc $CB                     ; $D811: 65 CB
00D813  1  48               pha                         ; $D813: 48
00D814  1                                               ; Preserve the calculated table index.
00D814  1               
00D814  1  20 B7 E6         jsr ClearMovementTransforms                   ; $D814: 20 B7 E6
00D817  1               
00D817  1  68               pla                         ; $D817: 68
00D818  1  A8               tay                         ; $D818: A8
00D819  1                                               ; Y = table index.
00D819  1               
00D819  1               ; ----------------------------------------------------------------------------
00D819  1               ; Carry from $E6B7 selects whether the animation-frame update is skipped.
00D819  1               ; ----------------------------------------------------------------------------
00D819  1               
00D819  1  B0 16            bcs SelectAnimationDelay    ; $D819: B0 16
00D81B  1               
00D81B  1               ; ----------------------------------------------------------------------------
00D81B  1               ; Read the current animation frame, then increment it.
00D81B  1               ;
00D81B  1               ; The original value remains in A for the following table comparisons.
00D81B  1               ; ----------------------------------------------------------------------------
00D81B  1               
00D81B  1  BD 9A 03         lda $039A,x                 ; $D81B: BD 9A 03
00D81E  1  FE 9A 03         inc $039A,x                 ; $D81E: FE 9A 03
00D821  1               
00D821  1               ; ----------------------------------------------------------------------------
00D821  1               ; Compare the original frame against two table thresholds.
00D821  1               ;
00D821  1               ; If it falls within the selected range, replace the animation frame with a
00D821  1               ; value from the table at $D837.
00D821  1               ; ----------------------------------------------------------------------------
00D821  1               
00D821  1  D9 43 D8         cmp AnimationFrameLimitTable,y            ; $D821: D9 43 D8
00D824  1  B0 05            bcs CheckLowerFrameBound    ; $D824: B0 05
00D826  1               
00D826  1  D9 37 D8         cmp AnimationFrameBaseTable,y            ; $D826: D9 37 D8
00D829  1  B0 06            bcs SelectAnimationDelay    ; $D829: B0 06
00D82B  1               
00D82B  1               CheckLowerFrameBound:           ; $D82B
00D82B  1  B9 37 D8         lda AnimationFrameBaseTable,y            ; $D82B: B9 37 D8
00D82E  1  9D 9A 03         sta $039A,x                 ; $D82E: 9D 9A 03
00D831  1               
00D831  1               ; ----------------------------------------------------------------------------
00D831  1               ; Select the delay associated with the table entry and tail-call $EB41.
00D831  1               ; ----------------------------------------------------------------------------
00D831  1               
00D831  1               SelectAnimationDelay:           ; $D831
00D831  1  B9 4F D8         lda AnimationFrameDelayTable,y            ; $D831: B9 4F D8
00D834  1  4C 41 EB         jmp StoreObjectEventBankValue                   ; $D834: 4C 41 EB
00D837  1               
00D837  1               ; ============================================================================
00D837  1               ; $D837-$D85A
00D837  1               ; Parallel animation-frame and delay lookup tables.
00D837  1               ;
00D837  1               ; SelectAnimationFrameAndDelay uses the same Y index with all three tables:
00D837  1               ;
00D837  1               ;   AnimationFrameBaseTable,Y = replacement or lower animation frame
00D837  1               ;   AnimationFrameLimitTable,Y = upper animation-frame threshold
00D837  1               ;   AnimationFrameDelayTable,Y = animation delay
00D837  1               ;
00D837  1               ; Each table contains twelve entries.
00D837  1               ; ============================================================================
00D837  1               
00D837  1               ; ----------------------------------------------------------------------------
00D837  1               ; Replacement/lower animation frames.
00D837  1               ; ----------------------------------------------------------------------------
00D837  1               
00D837  1               AnimationFrameBaseTable:        ; $D837
00D837  1  4D 50 53 56      .byte $4D,$50,$53,$56
00D83B  1  5C 61 1A 1E      .byte $5C,$61,$1A,$1E
00D83F  1  23 27 2F 32      .byte $23,$27,$2F,$32
00D843  1               
00D843  1               ; ----------------------------------------------------------------------------
00D843  1               ; Upper animation-frame thresholds.
00D843  1               ; ----------------------------------------------------------------------------
00D843  1               
00D843  1               AnimationFrameLimitTable:       ; $D843
00D843  1  4F 52 55 58      .byte $4F,$52,$55,$58
00D847  1  5D 63 1C 20      .byte $5D,$63,$1C,$20
00D84B  1  25 29 31 34      .byte $25,$29,$31,$34
00D84F  1               
00D84F  1               ; ----------------------------------------------------------------------------
00D84F  1               ; Delay associated with each animation range.
00D84F  1               ;
00D84F  1               ; Most ranges wait six ticks. Entry four uses nine ticks.
00D84F  1               ; ----------------------------------------------------------------------------
00D84F  1               
00D84F  1               AnimationFrameDelayTable:       ; $D84F
00D84F  1  06 06 06 06      .byte $06,$06,$06,$06
00D853  1  09 06 06 06      .byte $09,$06,$06,$06
00D857  1  06 06 06 06      .byte $06,$06,$06,$06
00D85B  1               
00D85B  1               ; ============================================================================
00D85B  1               ; $D85B-$D884
00D85B  1               ; Process three object-state entries.
00D85B  1               ;
00D85B  1               ; For each nonnegative entry in $0599-$059B:
00D85B  1               ;   1. Dispatch an object-specific inline command.
00D85B  1               ;   2. Wait for the next frame before checking the following entry.
00D85B  1               ;
00D85B  1               ; Negative entries are inactive and skip their associated command.
00D85B  1               ; ============================================================================
00D85B  1               
00D85B  1               ProcessSecondaryObjectStates:   ; $D85B
00D85B  1  AD 99 05         lda $0599                   ; $D85B: AD 99 05
00D85E  1  30 06            bmi CheckObjectState059A    ; $D85E: 30 06
00D860  1               
00D860  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $D860: 20 0A EB
00D863  1               
00D863  1                   ; Inline command record consumed by QueueInlineObjectEvent.
00D863  1  08 84 D8         .byte $08,$84,$D8           ; $D863-$D865
00D866  1               
00D866  1               ; ----------------------------------------------------------------------------
00D866  1               ; Wait for a frame before processing the second state entry.
00D866  1               ;
00D866  1               ; A negative first entry branches directly here.
00D866  1               ; ----------------------------------------------------------------------------
00D866  1               
00D866  1               CheckObjectState059A:           ; $D866
00D866  1  20 48 EB         jsr SelectObjectEventBank1                   ; $D866: 20 48 EB
00D869  1               
00D869  1  AD 9A 05         lda $059A                   ; $D869: AD 9A 05
00D86C  1  30 06            bmi CheckObjectState059B    ; $D86C: 30 06
00D86E  1               
00D86E  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $D86E: 20 0A EB
00D871  1               
00D871  1                   ; Inline command record consumed by QueueInlineObjectEvent.
00D871  1  0A 84 D8         .byte $0A,$84,$D8           ; $D871-$D873
00D874  1               
00D874  1               ; ----------------------------------------------------------------------------
00D874  1               ; Wait for a frame before processing the third state entry.
00D874  1               ;
00D874  1               ; A negative second entry branches directly here.
00D874  1               ; ----------------------------------------------------------------------------
00D874  1               
00D874  1               CheckObjectState059B:           ; $D874
00D874  1  20 48 EB         jsr SelectObjectEventBank1                   ; $D874: 20 48 EB
00D877  1               
00D877  1  AD 9B 05         lda $059B                   ; $D877: AD 9B 05
00D87A  1  30 06            bmi FinishSecondaryObjectStates
00D87C  1                                               ; $D87A: 30 06
00D87C  1               
00D87C  1  20 0A EB         jsr QueueInlineObjectEvent                   ; $D87C: 20 0A EB
00D87F  1               
00D87F  1                   ; Inline command record consumed by QueueInlineObjectEvent.
00D87F  1  0C 84 D8         .byte $0C,$84,$D8           ; $D87F-$D881
00D882  1               
00D882  1               ; ----------------------------------------------------------------------------
00D882  1               ; Leave through the common engine exit.
00D882  1               ; ----------------------------------------------------------------------------
00D882  1               
00D882  1               FinishSecondaryObjectStates:    ; $D882
00D882  1  4C 6A EB         jmp CommonEngineExit                   ; $D882: 4C 6A EB
00D885  1               
00D885  1               ; ============================================================================
00D885  1               ; $D885-$D8C2
00D885  1               ; Update one secondary object's active state.
00D885  1               ;
00D885  1               ; Entry:
00D885  1               ;   X = object-array offset supplied by the inline command record:
00D885  1               ;       $08, $0A, or $0C
00D885  1               ;
00D885  1               ; The routine updates the indexed timer/state fields, performs collision or
00D885  1               ; geometry checks, waits for frame updates, and dispatches to later state paths.
00D885  1               ; ============================================================================
00D885  1               
00D885  1               UpdateSecondaryObjectState:     ; $D885
00D885  1  20 68 DA         jsr GetCurrentObjectStateIndex
00D888  1                                               ; $D885: 20 68 DA
00D888  1               
00D888  1               ; ----------------------------------------------------------------------------
00D888  1               ; Increment this object's state/timer at $0595,X.
00D888  1               ;
00D888  1               ; If the incremented value is nonzero, skip the initialization delay and
00D888  1               ; continue at $D897.
00D888  1               ; ----------------------------------------------------------------------------
00D888  1               
00D888  1  FE 95 05         inc $0595,x                 ; $D888: FE 95 05
00D88B  1  D0 0A            bne SecondaryObject_CheckRegion
00D88D  1                                               ; $D88B: D0 0A
00D88D  1               
00D88D  1               ; ----------------------------------------------------------------------------
00D88D  1               ; Handle wraparound from $FF to $00.
00D88D  1               ;
00D88D  1               ; The helper at $DBB8 returns a delay value in A, which is passed directly to
00D88D  1               ; the timing helper at $EB41.
00D88D  1               ; ----------------------------------------------------------------------------
00D88D  1               SecondaryObject_RetryDelay:
00D88D  1  20 B8 DB         jsr SelectSecondaryObjectDelay                   ; $D88D: 20 B8 DB
00D890  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $D890: 20 41 EB
00D893  1               
00D893  1  A5 7F            lda SelectedStateCount      ; $D893: A5 7F
00D895  1  D0 2C            bne SecondaryObject_ActivateTimer
00D897  1                                               ; $D895: D0 2C
00D897  1               
00D897  1               ; ----------------------------------------------------------------------------
00D897  1               ; Run the object's geometry/update helpers.
00D897  1               ;
00D897  1               ; If $E55F returns carry set, restart at $D88D and choose another delay.
00D897  1               ; ----------------------------------------------------------------------------
00D897  1               
00D897  1               SecondaryObject_CheckRegion:    ; $D897
00D897  1  20 81 E4         jsr SelectGeometryRecord_44                   ; $D897: 20 81 E4
00D89A  1  20 5F E5         jsr ApplyCurrentObjectGeometry                   ; $D89A: 20 5F E5
00D89D  1  B0 EE            bcs SecondaryObject_RetryDelay
00D89F  1                                               ; $D89D: B0 EE
00D89F  1               
00D89F  1               ; ----------------------------------------------------------------------------
00D89F  1               ; Update object data, recalculate X, then clear $96,X.
00D89F  1               ;
00D89F  1               ; The helper at GetCurrentObjectStateIndex appears to restore or derive the
00D89F  1               ; object-relative index required by the indexed store.
00D89F  1               ; ----------------------------------------------------------------------------
00D89F  1               
00D89F  1  20 81 DA         jsr UpdateCurrentObjectAnimation
00D8A2  1                                               ; $D89F: 20 81 DA
00D8A2  1  20 68 DA         jsr GetCurrentObjectStateIndex
00D8A5  1                                               ; $D8A2: 20 68 DA
00D8A5  1               
00D8A5  1  A9 00            lda #$00                    ; $D8A5: A9 00
00D8A7  1  95 96            sta $96,x                   ; $D8A7: 95 96
00D8A9  1               
00D8A9  1               ; ----------------------------------------------------------------------------
00D8A9  1               ; Wait for the next frame and evaluate the current global state.
00D8A9  1               ; ----------------------------------------------------------------------------
00D8A9  1               
00D8A9  1               SecondaryObject_WaitFrame:      ; $D8A9
00D8A9  1  20 48 EB         jsr SelectObjectEventBank1                   ; $D8A9: 20 48 EB
00D8AC  1               
00D8AC  1  A5 86            lda TrajectoryEvaluationEnabled                 ; $D8AC: A5 86
00D8AE  1  F0 03            beq SecondaryObject_CheckFlags
00D8B0  1                                               ; $D8AE: F0 03
00D8B0  1               
00D8B0  1  4C 44 D9         jmp SecondaryObject_State86Path
00D8B3  1                                               ; $D8B0: 4C 44 D9
00D8B3  1               
00D8B3  1               ; ----------------------------------------------------------------------------
00D8B3  1               ; When either $82 or $7F is nonzero, continue at the timer activation path.
00D8B3  1               ; ----------------------------------------------------------------------------
00D8B3  1               
00D8B3  1               SecondaryObject_CheckFlags:     ; $D8B3
00D8B3  1  A5 82            lda ActorActionComplete                 ; $D8B3: A5 82
00D8B5  1  D0 0C            bne SecondaryObject_ActivateTimer
00D8B7  1                                               ; $D8B5: D0 0C
00D8B7  1               
00D8B7  1  A5 7F            lda SelectedStateCount      ; $D8B7: A5 7F
00D8B9  1  D0 08            bne SecondaryObject_ActivateTimer
00D8BB  1                                               ; $D8B9: D0 08
00D8BB  1               
00D8BB  1               ; ----------------------------------------------------------------------------
00D8BB  1               ; Run the helper at $DB18.
00D8BB  1               ;
00D8BB  1               ; A nonnegative result returns to the frame wait. A negative result transfers
00D8BB  1               ; to the later state path at $DA25.
00D8BB  1               ; ----------------------------------------------------------------------------
00D8BB  1               
00D8BB  1  20 18 DB         jsr TestCurrentObjectInput                   ; $D8BB: 20 18 DB
00D8BE  1  10 E9            bpl SecondaryObject_WaitFrame
00D8C0  1                                               ; $D8BE: 10 E9
00D8C0  1               
00D8C0  1  4C 25 DA         jmp SecondaryObject_NegativeResultPath
00D8C3  1                                               ; $D8C0: 4C 25 DA
00D8C3  1               
00D8C3  1               
00D8C3  1               ; ============================================================================
00D8C3  1               ; $D8C3-$D905
00D8C3  1               ; Secondary-object timer path.
00D8C3  1               ;
00D8C3  1               ; This path initializes the object's timer, waits for state conditions,
00D8C3  1               ; processes the object each frame, performs a collision/region check when the
00D8C3  1               ; timer expires, and dispatches to the appropriate result path.
00D8C3  1               ; ============================================================================
00D8C3  1               
00D8C3  1               SecondaryObject_ActivateTimer:  ; $D8C3
00D8C3  1  A9 01            lda #$01                    ; $D8C3: A9 01
00D8C5  1               SecondaryObject_SetTimer:
00D8C5  1  A6 E1            ldx CurrentObjectIndex      ; $D8C5: A6 E1
00D8C7  1  9D B1 05         sta $05B1,x                 ; $D8C7: 9D B1 05
00D8CA  1               
00D8CA  1               ; ----------------------------------------------------------------------------
00D8CA  1               ; Wait for the next frame and derive the current object-relative index.
00D8CA  1               ; ----------------------------------------------------------------------------
00D8CA  1               
00D8CA  1               SecondaryObject_TimerLoop:      ; $D8CA
00D8CA  1  20 48 EB         jsr SelectObjectEventBank1                   ; $D8CA: 20 48 EB
00D8CD  1               
00D8CD  1  20 68 DA         jsr GetCurrentObjectStateIndex
00D8D0  1                                               ; $D8CD: 20 68 DA
00D8D0  1               
00D8D0  1               ; ----------------------------------------------------------------------------
00D8D0  1               ; If the indexed state at $96,X is nonzero, continue with normal object
00D8D0  1               ; processing.
00D8D0  1               ; ----------------------------------------------------------------------------
00D8D0  1               
00D8D0  1  B5 96            lda $96,x                   ; $D8D0: B5 96
00D8D2  1  D0 08            bne SecondaryObject_ProcessFrame
00D8D4  1                                               ; $D8D2: D0 08
00D8D4  1               
00D8D4  1               ; ----------------------------------------------------------------------------
00D8D4  1               ; Otherwise, run the helper at $DB18.
00D8D4  1               ;
00D8D4  1               ; A nonnegative result continues normal processing. A negative result transfers
00D8D4  1               ; to the common negative-result path at $DA25.
00D8D4  1               ; ----------------------------------------------------------------------------
00D8D4  1               
00D8D4  1  20 18 DB         jsr TestCurrentObjectInput                   ; $D8D4: 20 18 DB
00D8D7  1  10 03            bpl SecondaryObject_ProcessFrame
00D8D9  1                                               ; $D8D7: 10 03
00D8D9  1               
00D8D9  1  4C 25 DA         jmp SecondaryObject_NegativeResultPath
00D8DC  1                                               ; $D8D9: 4C 25 DA
00D8DC  1               
00D8DC  1               ; ----------------------------------------------------------------------------
00D8DC  1               ; Run the per-frame object helper.
00D8DC  1               ; ----------------------------------------------------------------------------
00D8DC  1               
00D8DC  1               SecondaryObject_ProcessFrame:   ; $D8DC
00D8DC  1  20 BC DA         jsr CheckCurrentObjectSelector                   ; $D8DC: 20 BC DA
00D8DF  1               
00D8DF  1               ; ----------------------------------------------------------------------------
00D8DF  1               ; Count down this object's timer at $05B1,X.
00D8DF  1               ;
00D8DF  1               ; Continue the frame loop until the timer reaches zero.
00D8DF  1               ; ----------------------------------------------------------------------------
00D8DF  1               
00D8DF  1  A6 E1            ldx CurrentObjectIndex      ; $D8DF: A6 E1
00D8E1  1               
00D8E1  1  DE B1 05         dec $05B1,x                 ; $D8E1: DE B1 05
00D8E4  1  D0 E4            bne SecondaryObject_TimerLoop
00D8E6  1                                               ; $D8E4: D0 E4
00D8E6  1               
00D8E6  1               ; ----------------------------------------------------------------------------
00D8E6  1               ; Timer expired. Run geometry/collision helpers.
00D8E6  1               ; ----------------------------------------------------------------------------
00D8E6  1               
00D8E6  1  20 A5 E4         jsr SelectGeometryRecord_24                   ; $D8E6: 20 A5 E4
00D8E9  1  20 5F E5         jsr ApplyCurrentObjectGeometry                   ; $D8E9: 20 5F E5
00D8EC  1               
00D8EC  1  90 06            bcc SecondaryObject_NoCollision
00D8EE  1                                               ; $D8EC: 90 06
00D8EE  1               
00D8EE  1               ; ----------------------------------------------------------------------------
00D8EE  1               ; Collision or region test succeeded.
00D8EE  1               ;
00D8EE  1               ; Select a delay and re-enter the object-processing path at $D8C5. This entry
00D8EE  1               ; reloads X from CurrentObjectIndex and stores the selected delay in $05B1,X.
00D8EE  1               ; ----------------------------------------------------------------------------
00D8EE  1               
00D8EE  1  20 B8 DB         jsr SelectSecondaryObjectDelay                   ; $D8EE: 20 B8 DB
00D8F1  1  4C C5 D8         jmp SecondaryObject_SetTimer
00D8F4  1                                               ; $D8F1: 4C C5 D8
00D8F4  1               
00D8F4  1               ; ----------------------------------------------------------------------------
00D8F4  1               ; Collision or region test did not succeed.
00D8F4  1               ;
00D8F4  1               ; Decrement the indexed object state and process the resulting transition.
00D8F4  1               ; ----------------------------------------------------------------------------
00D8F4  1               
00D8F4  1               SecondaryObject_NoCollision:    ; $D8F4
00D8F4  1  20 68 DA         jsr GetCurrentObjectStateIndex
00D8F7  1                                               ; $D8F4: 20 68 DA
00D8F7  1               
00D8F7  1  DE 95 05         dec $0595,x                 ; $D8F7: DE 95 05
00D8FA  1               
00D8FA  1  20 A4 DA         jsr CountMatchingObjectStates                   ; $D8FA: 20 A4 DA
00D8FD  1  20 F7 DA         jsr UpdateCurrentObjectSelectorState                   ; $D8FD: 20 F7 DA
00D900  1  20 EB DA         jsr StoreCurrentObjectSelector                   ; $D900: 20 EB DA
00D903  1               
00D903  1  4C 0C D9         jmp SecondaryObject_Continue
00D906  1                                               ; $D903: 4C 0C D9
00D906  1               
00D906  1               ; ============================================================================
00D906  1               ; $D906-$D943
00D906  1               ; Retry object geometry processing, update indexed state, and select the next
00D906  1               ; secondary-object transition path.
00D906  1               ; ============================================================================
00D906  1               
00D906  1               SecondaryObject_RetryGeometry:  ; $D906
00D906  1  20 B8 DB         jsr SelectSecondaryObjectDelay                   ; $D906: 20 B8 DB
00D909  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $D909: 20 41 EB
00D90C  1               
00D90C  1               ; ----------------------------------------------------------------------------
00D90C  1               ; Run geometry/region helpers.
00D90C  1               ;
00D90C  1               ; If the region test returns carry set, select another delay and retry.
00D90C  1               ; ----------------------------------------------------------------------------
00D90C  1               
00D90C  1               SecondaryObject_Continue:       ; $D90C
00D90C  1  20 8F E4         jsr SelectGeometryRecord_34                   ; $D90C: 20 8F E4
00D90F  1  20 5F E5         jsr ApplyCurrentObjectGeometry                   ; $D90F: 20 5F E5
00D912  1               
00D912  1  B0 F2            bcs SecondaryObject_RetryGeometry
00D914  1                                               ; $D912: B0 F2
00D914  1               
00D914  1               ; ----------------------------------------------------------------------------
00D914  1               ; Update object state, wait for the next frame, and derive the current
00D914  1               ; object-relative index.
00D914  1               ; ----------------------------------------------------------------------------
00D914  1               
00D914  1  20 81 DA         jsr UpdateCurrentObjectAnimation
00D917  1                                               ; $D914: 20 81 DA
00D917  1               
00D917  1               SecondaryObject_StateLoop:      ; $D917
00D917  1  20 48 EB         jsr SelectObjectEventBank1                   ; $D917: 20 48 EB
00D91A  1               
00D91A  1  20 6D DA         jsr MarkMatchingObjectState ; $D91A: 20 6D DA
00D91D  1               
00D91D  1               ; ----------------------------------------------------------------------------
00D91D  1               ; If state $6E is nonzero, evaluate the current indexed object condition.
00D91D  1               ; A negative result branches to the transition path at $D941.
00D91D  1               ; ----------------------------------------------------------------------------
00D91D  1               
00D91D  1  A5 6E            lda ObjectTransitionState                 ; $D91D: A5 6E
00D91F  1  F0 0A            beq SecondaryObject_CheckState6D
00D921  1                                               ; $D91F: F0 0A
00D921  1               
00D921  1  20 5F DA         jsr GetCurrentObjectSelector; $D921: 20 5F DA
00D924  1  30 1B            bmi SecondaryObject_Transition
00D926  1                                               ; $D924: 30 1B
00D926  1               
00D926  1               ; ----------------------------------------------------------------------------
00D926  1               ; Increment the indexed object-state byte at $96,X.
00D926  1               ; ----------------------------------------------------------------------------
00D926  1               
00D926  1  20 68 DA         jsr GetCurrentObjectStateIndex
00D929  1                                               ; $D926: 20 68 DA
00D929  1  F6 96            inc $96,x                   ; $D929: F6 96
00D92B  1               
00D92B  1               ; ----------------------------------------------------------------------------
00D92B  1               ; State $6D immediately selects the transition path when nonzero.
00D92B  1               ; ----------------------------------------------------------------------------
00D92B  1               
00D92B  1               SecondaryObject_CheckState6D:   ; $D92B
00D92B  1  A5 6D            lda SpecialSequenceState                 ; $D92B: A5 6D
00D92D  1  D0 12            bne SecondaryObject_Transition
00D92F  1                                               ; $D92D: D0 12
00D92F  1               
00D92F  1               ; ----------------------------------------------------------------------------
00D92F  1               ; If both BaseMotionPhase and PendingStateTransition are zero, evaluate GetCurrentObjectSelector.
00D92F  1               ;
00D92F  1               ; A negative result selects the transition path.
00D92F  1               ; ----------------------------------------------------------------------------
00D92F  1               
00D92F  1  A5 5D            lda BaseMotionPhase             ; $D92F: A5 5D
00D931  1  F0 09            beq SecondaryObject_CheckResult
00D933  1                                               ; $D931: F0 09
00D933  1               
00D933  1  A5 60            lda PendingStateTransition                 ; $D933: A5 60
00D935  1  D0 05            bne SecondaryObject_CheckResult
00D937  1                                               ; $D935: D0 05
00D937  1               
00D937  1  20 5F DA         jsr GetCurrentObjectSelector; $D937: 20 5F DA
00D93A  1  30 05            bmi SecondaryObject_Transition
00D93C  1                                               ; $D93A: 30 05
00D93C  1               
00D93C  1               ; ----------------------------------------------------------------------------
00D93C  1               ; Continue waiting while $DB18 returns a nonnegative result.
00D93C  1               ; ----------------------------------------------------------------------------
00D93C  1               
00D93C  1               SecondaryObject_CheckResult:    ; $D93C
00D93C  1  20 18 DB         jsr TestCurrentObjectInput                   ; $D93C: 20 18 DB
00D93F  1  10 D6            bpl SecondaryObject_StateLoop
00D941  1                                               ; $D93F: 10 D6
00D941  1               
00D941  1               ; ----------------------------------------------------------------------------
00D941  1               ; Transfer to the later transition handler.
00D941  1               ; ----------------------------------------------------------------------------
00D941  1               
00D941  1               SecondaryObject_Transition:     ; $D941
00D941  1  4C E6 D9         jmp SecondaryObject_TransitionHandler                   ; $D941: 4C E6 D9
00D944  1               
00D944  1               ; ============================================================================
00D944  1               ; $D944-$D95F
00D944  1               ; State-86 path for the secondary-object handler.
00D944  1               ; ============================================================================
00D944  1               
00D944  1               SecondaryObject_State86Path:    ; $D944
00D944  1  A5 64            lda SecondarySequenceState                 ; $D944: A5 64
00D946  1  C9 02            cmp #$02                    ; $D946: C9 02
00D948  1  F0 10            beq SecondaryObject_JumpToNegativeResult
00D94A  1                                               ; $D948: F0 10
00D94A  1               
00D94A  1               ; ----------------------------------------------------------------------------
00D94A  1               ; Wait for the next frame.
00D94A  1               ; ----------------------------------------------------------------------------
00D94A  1               
00D94A  1               SecondaryObject_State86Wait:    ; $D94A
00D94A  1  20 48 EB         jsr SelectObjectEventBank1                   ; $D94A: 20 48 EB
00D94D  1               
00D94D  1               ; ----------------------------------------------------------------------------
00D94D  1               ; If the sequence-state counter is nonzero, return to the timer path.
00D94D  1               ; ----------------------------------------------------------------------------
00D94D  1               
00D94D  1  A5 A2            lda ObjectSequenceState           ; $D94D: A5 A2
00D94F  1  D0 0C            bne SecondaryObject_TimerPath
00D951  1                                               ; $D94F: D0 0C
00D951  1               
00D951  1               ; ----------------------------------------------------------------------------
00D951  1               ; Continue waiting while BaseMotionPhase is zero.
00D951  1               ; ----------------------------------------------------------------------------
00D951  1               
00D951  1  A5 5D            lda BaseMotionPhase             ; $D951: A5 5D
00D953  1  F0 F5            beq SecondaryObject_State86Wait
00D955  1                                               ; $D953: F0 F5
00D955  1               
00D955  1               ; ----------------------------------------------------------------------------
00D955  1               ; Evaluate the current object result.
00D955  1               ;
00D955  1               ; A nonnegative result returns to the timer path. A negative result falls
00D955  1               ; through to a trampoline that jumps to the real handler at $DA25.
00D955  1               ; ----------------------------------------------------------------------------
00D955  1               
00D955  1  20 5F DA         jsr GetCurrentObjectSelector; $D955: 20 5F DA
00D958  1  10 03            bpl SecondaryObject_TimerPath
00D95A  1                                               ; $D958: 10 03
00D95A  1               
00D95A  1               SecondaryObject_JumpToNegativeResult: ; $D95A
00D95A  1  4C 25 DA         jmp SecondaryObject_NegativeResultPath
00D95D  1                                               ; $D95A: 4C 25 DA
00D95D  1               
00D95D  1               ; ----------------------------------------------------------------------------
00D95D  1               ; Re-enter the timer initialization path.
00D95D  1               ; ----------------------------------------------------------------------------
00D95D  1               
00D95D  1               SecondaryObject_TimerPath:      ; $D95D
00D95D  1  4C C3 D8         jmp SecondaryObject_ActivateTimer
00D960  1                                               ; $D95D: 4C C3 D8
00D960  1               
00D960  1               ; ============================================================================
00D960  1               ; $D960-$D966
00D960  1               ; Route according to the global action state.
00D960  1               ; ============================================================================
00D960  1               
00D960  1               SecondaryObject_ActionStatePath: ; $D960
00D960  1  A5 9D            lda CurrentActionState             ; $D960: A5 9D
00D962  1  D0 33            bne SecondaryObject_ActionActive
00D964  1                                               ; $D962: D0 33
00D964  1               
00D964  1  4C 85 D8         jmp UpdateSecondaryObjectState
00D967  1                                               ; $D964: 4C 85 D8
00D967  1               
00D967  1               ; ============================================================================
00D967  1               ; $D967-$D990
00D967  1               ; Advance the indexed secondary-object state, run its update helpers, and
00D967  1               ; select the next path using the current event and object indices.
00D967  1               ; ============================================================================
00D967  1               
00D967  1               SecondaryObject_AdvanceIndexedState: ; $D967
00D967  1  20 68 DA         jsr GetCurrentObjectStateIndex
00D96A  1                                                    ; $D967: 20 68 DA
00D96A  1               
00D96A  1               ; ----------------------------------------------------------------------------
00D96A  1               ; Advance the indexed state byte at $0595,X.
00D96A  1               ; ----------------------------------------------------------------------------
00D96A  1               
00D96A  1  FE 95 05         inc $0595,x                 ; $D96A: FE 95 05
00D96D  1               
00D96D  1               ; ----------------------------------------------------------------------------
00D96D  1               ; Derive an object/event selector in Y.
00D96D  1               ;
00D96D  1               ; A selector value of eight transfers to the special path at $D9B3.
00D96D  1               ; ----------------------------------------------------------------------------
00D96D  1               
00D96D  1  20 DC E3         jsr GetCurrentObjectSelectorAndState
00D970  1                                              ; $D96D: 20 DC E3
00D970  1               
00D970  1  C0 08            cpy #$08                    ; $D970: C0 08
00D972  1  F0 3F            beq SecondaryObject_SelectorEight
00D974  1                                               ; $D972: F0 3F
00D974  1               
00D974  1               ; ----------------------------------------------------------------------------
00D974  1               ; Run the normal indexed-object update helpers.
00D974  1               ; ----------------------------------------------------------------------------
00D974  1               
00D974  1  20 A4 DA         jsr CountMatchingObjectStates                   ; $D974: 20 A4 DA
00D977  1  20 F7 DA         jsr UpdateCurrentObjectSelectorState                   ; $D977: 20 F7 DA
00D97A  1  20 EB DA         jsr StoreCurrentObjectSelector                   ; $D97A: 20 EB DA
00D97D  1               
00D97D  1               ; ----------------------------------------------------------------------------
00D97D  1               ; If state $6D is zero, return to the action-state dispatcher at $D960.
00D97D  1               ; ----------------------------------------------------------------------------
00D97D  1               
00D97D  1  A5 6D            lda SpecialSequenceState                 ; $D97D: A5 6D
00D97F  1  F0 DF            beq SecondaryObject_ActionStatePath
00D981  1                                               ; $D97F: F0 DF
00D981  1               
00D981  1               ; ----------------------------------------------------------------------------
00D981  1               ; Recalculate the event selector and convert it into an object-related index.
00D981  1               ;
00D981  1               ; Calculation:
00D981  1               ;
00D981  1               ;   A = ((Y >> 1) + 4 - SpecialSequenceState) * 2
00D981  1               ; ----------------------------------------------------------------------------
00D981  1               SecondaryObject_RecalculateSelector:
00D981  1  20 DC E3         jsr GetCurrentObjectSelectorAndState
00D984  1                                               ; $D981: 20 DC E3
00D984  1               
00D984  1  98               tya                         ; $D984: 98
00D985  1  4A               lsr                         ; $D985: 4A
00D986  1               
00D986  1  69 04            adc #$04                    ; $D986: 69 04
00D988  1  E5 6D            sbc SpecialSequenceState                 ; $D988: E5 6D
00D98A  1               
00D98A  1  0A               asl                         ; $D98A: 0A
00D98B  1               
00D98B  1               ; ----------------------------------------------------------------------------
00D98B  1               ; Compare the calculated object offset against CurrentObjectIndex.
00D98B  1               ;
00D98B  1               ; If the calculated offset is below the current object index, branch to the
00D98B  1               ; transition handler at $D9E6. Otherwise, continue at $D997.
00D98B  1               ;
00D98B  1               ; The BCS at $D98F is effectively unconditional if the preceding BCC was not
00D98B  1               ; taken because CMP establishes carry.
00D98B  1               ; ----------------------------------------------------------------------------
00D98B  1               
00D98B  1  C5 E1            cmp CurrentObjectIndex      ; $D98B: C5 E1
00D98D  1  90 57            bcc SecondaryObject_TransitionHandler
00D98F  1                                               ; $D98D: 90 57
00D98F  1               
00D98F  1  B0 06            bcs SecondaryObject_ActionActive
00D991  1                                               ; $D98F: B0 06
00D991  1               
00D991  1               ; ============================================================================
00D991  1               ; $D991-$D9B2
00D991  1               ; Secondary-object delay retry and action-active paths.
00D991  1               ;
00D991  1               ; The retry path repeatedly selects a delay and performs a geometry test.
00D991  1               ; Once the test succeeds, the action-active path updates the object and waits
00D991  1               ; until another state condition selects either the normal loop or transition.
00D991  1               ; ============================================================================
00D991  1               
00D991  1               SecondaryObject_RetryPath:      ; $D991
00D991  1  20 B8 DB         jsr SelectSecondaryObjectDelay                   ; $D991: 20 B8 DB
00D994  1                                               ; Select a delay value in A.
00D994  1               
00D994  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $D994: 20 41 EB
00D997  1                                               ; Wait for the selected delay.
00D997  1               
00D997  1               ; ----------------------------------------------------------------------------
00D997  1               ; Real entry for the action-active path.
00D997  1               ;
00D997  1               ; The BCS at $D98F branches here when the calculated object offset is greater
00D997  1               ; than or equal to CurrentObjectIndex.
00D997  1               ; ----------------------------------------------------------------------------
00D997  1               
00D997  1               SecondaryObject_ActionActive:   ; $D997
00D997  1  20 8F E4         jsr SelectGeometryRecord_34                   ; $D997: 20 8F E4
00D99A  1  20 5F E5         jsr ApplyCurrentObjectGeometry                   ; $D99A: 20 5F E5
00D99D  1               
00D99D  1  B0 F2            bcs SecondaryObject_RetryPath
00D99F  1                                               ; $D99D: B0 F2
00D99F  1               
00D99F  1               ; ----------------------------------------------------------------------------
00D99F  1               ; Geometry test succeeded. Update the current object and wait for a frame.
00D99F  1               ; ----------------------------------------------------------------------------
00D99F  1               
00D99F  1  20 81 DA         jsr UpdateCurrentObjectAnimation
00D9A2  1                                               ; $D99F: 20 81 DA
00D9A2  1               
00D9A2  1               SecondaryObject_ActionWait:     ; $D9A2
00D9A2  1  20 48 EB         jsr SelectObjectEventBank1                   ; $D9A2: 20 48 EB
00D9A5  1               
00D9A5  1               ; ----------------------------------------------------------------------------
00D9A5  1               ; If SpecialSequenceState is nonzero, return to the selector calculation at $D981.
00D9A5  1               ; ----------------------------------------------------------------------------
00D9A5  1               
00D9A5  1  A5 6D            lda SpecialSequenceState                 ; $D9A5: A5 6D
00D9A7  1  D0 D8            bne SecondaryObject_RecalculateSelector
00D9A9  1                                               ; $D9A7: D0 D8
00D9A9  1               
00D9A9  1               ; ----------------------------------------------------------------------------
00D9A9  1               ; Run the per-frame object helper, then evaluate the result from $DB18.
00D9A9  1               ; ----------------------------------------------------------------------------
00D9A9  1               
00D9A9  1  20 BC DA         jsr CheckCurrentObjectSelector                   ; $D9A9: 20 BC DA
00D9AC  1               
00D9AC  1  20 18 DB         jsr TestCurrentObjectInput                   ; $D9AC: 20 18 DB
00D9AF  1  10 F1            bpl SecondaryObject_ActionWait
00D9B1  1                                               ; $D9AF: 10 F1
00D9B1  1               
00D9B1  1               ; ----------------------------------------------------------------------------
00D9B1  1               ; A negative result transfers to the transition handler at $D9E6.
00D9B1  1               ; ----------------------------------------------------------------------------
00D9B1  1               
00D9B1  1  30 33            bmi SecondaryObject_TransitionHandler
00D9B3  1                                               ; $D9B1: 30 33
00D9B3  1               
00D9B3  1               ; ============================================================================
00D9B3  1               ; $D9B3-$D9E5
00D9B3  1               ; Handle selector value eight, update pending state, and retry the geometry
00D9B3  1               ; test until the secondary object can complete its transition.
00D9B3  1               ; ============================================================================
00D9B3  1               
00D9B3  1               SecondaryObject_SelectorEight:  ; $D9B3
00D9B3  1  20 F7 DA         jsr UpdateCurrentObjectSelectorState                   ; $D9B3: 20 F7 DA
00D9B6  1  20 EB DA         jsr StoreCurrentObjectSelector                   ; $D9B6: 20 EB DA
00D9B9  1               
00D9B9  1               ; ----------------------------------------------------------------------------
00D9B9  1               ; When SecondarySequenceState has not reached three, increment PendingScoreIncrement.
00D9B9  1               ;
00D9B9  1               ; If CurrentActionState is zero, immediately apply the pending increment to the
00D9B9  1               ; counters/display and clear PendingScoreIncrement.
00D9B9  1               ; ----------------------------------------------------------------------------
00D9B9  1               
00D9B9  1  A5 64            lda SecondarySequenceState                 ; $D9B9: A5 64
00D9BB  1  C9 03            cmp #$03                    ; $D9BB: C9 03
00D9BD  1  F0 0D            beq SecondaryObject_RunFrameHelper
00D9BF  1                                               ; $D9BD: F0 0D
00D9BF  1               
00D9BF  1  E6 65            inc PendingScoreIncrement        ; $D9BF: E6 65
00D9C1  1               
00D9C1  1  A5 9D            lda CurrentActionState             ; $D9C1: A5 9D
00D9C3  1  D0 07            bne SecondaryObject_RunFrameHelper
00D9C5  1                                               ; $D9C3: D0 07
00D9C5  1               
00D9C5  1  20 A6 CF         jsr UpdateCountersAndDisplay
00D9C8  1                                               ; $D9C5: 20 A6 CF
00D9C8  1               
00D9C8  1  A9 00            lda #$00                    ; $D9C8: A9 00
00D9CA  1  85 65            sta PendingScoreIncrement        ; $D9CA: 85 65
00D9CC  1               
00D9CC  1               ; ----------------------------------------------------------------------------
00D9CC  1               ; Run the per-frame secondary-object helper and repeat the geometry test.
00D9CC  1               ; ----------------------------------------------------------------------------
00D9CC  1               
00D9CC  1               SecondaryObject_RunFrameHelper: ; $D9CC
00D9CC  1  20 BC DA         jsr CheckCurrentObjectSelector                   ; $D9CC: 20 BC DA
00D9CF  1               
00D9CF  1  20 8F E4         jsr SelectGeometryRecord_34                   ; $D9CF: 20 8F E4
00D9D2  1  20 5F E5         jsr ApplyCurrentObjectGeometry                   ; $D9D2: 20 5F E5
00D9D5  1               
00D9D5  1  90 09            bcc SecondaryObject_FinishSelectorEight
00D9D7  1                                               ; $D9D5: 90 09
00D9D7  1               
00D9D7  1               ; ----------------------------------------------------------------------------
00D9D7  1               ; Geometry test still blocks completion.
00D9D7  1               ;
00D9D7  1               ; Select a delay, wait, and retry from the per-frame helper at $D9CC.
00D9D7  1               ; ----------------------------------------------------------------------------
00D9D7  1               
00D9D7  1  20 B8 DB         jsr SelectSecondaryObjectDelay                   ; $D9D7: 20 B8 DB
00D9DA  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $D9DA: 20 41 EB
00D9DD  1               
00D9DD  1  4C CC D9         jmp SecondaryObject_RunFrameHelper
00D9E0  1                                               ; $D9DD: 4C CC D9
00D9E0  1               
00D9E0  1               ; ----------------------------------------------------------------------------
00D9E0  1               ; Geometry test completed. Update the object and leave through the common
00D9E0  1               ; engine exit.
00D9E0  1               ; ----------------------------------------------------------------------------
00D9E0  1               
00D9E0  1               SecondaryObject_FinishSelectorEight: ; $D9E0
00D9E0  1  20 81 DA         jsr UpdateCurrentObjectAnimation
00D9E3  1                                               ; $D9E0: 20 81 DA
00D9E3  1               
00D9E3  1  4C 6A EB         jmp CommonEngineExit                   ; $D9E3: 4C 6A EB
00D9E6  1               
00D9E6  1               ; ============================================================================
00D9E6  1               ; $D9E6-$DA0E
00D9E6  1               ; Secondary-object transition handler.
00D9E6  1               ;
00D9E6  1               ; Entry:
00D9E6  1               ;   X is restored or derived by GetCurrentObjectStateIndex.
00D9E6  1               ;
00D9E6  1               ; The handler advances the indexed object state. If that state becomes
00D9E6  1               ; nonzero, it transfers directly to the shared negative-result path at $DA25.
00D9E6  1               ; If the state wraps to zero, it loads a new inline position record and begins
00D9E6  1               ; a new object-processing cycle.
00D9E6  1               ; ============================================================================
00D9E6  1               
00D9E6  1               SecondaryObject_TransitionHandler: ; $D9E6
00D9E6  1  20 68 DA         jsr GetCurrentObjectStateIndex
00D9E9  1                                                  ; $D9E6: 20 68 DA
00D9E9  1               
00D9E9  1               ; ----------------------------------------------------------------------------
00D9E9  1               ; Advance the indexed state byte at $0595,X.
00D9E9  1               ;
00D9E9  1               ; A nonzero result transfers to the shared path at $DA25.
00D9E9  1               ; ----------------------------------------------------------------------------
00D9E9  1               
00D9E9  1  FE 95 05         inc $0595,x                 ; $D9E9: FE 95 05
00D9EC  1  D0 37            bne SecondaryObject_NegativeResultPath
00D9EE  1                                               ; $D9EC: D0 37
00D9EE  1               
00D9EE  1               ; ----------------------------------------------------------------------------
00D9EE  1               ; The indexed state wrapped from $FF to zero.
00D9EE  1               ;
00D9EE  1               ; Initialize object offset $06 with a new position record:
00D9EE  1               ;
00D9EE  1               ;   $0509,$X = $00
00D9EE  1               ;   $050A,$X = $01
00D9EE  1               ;   $053A,$X = $00
00D9EE  1               ;   $053B,$X = $F8
00D9EE  1               ; ----------------------------------------------------------------------------
00D9EE  1               
00D9EE  1  20 A7 C9         jsr LoadObjectPositionInline
00D9F1  1                                               ; $D9EE: 20 A7 C9
00D9F1  1               
00D9F1  1  06               .byte $06                   ; $D9F1: object offset/metadata
00D9F2  1  00 01 00 F8      .byte $00,$01,$00,$F8       ; $D9F2-$D9F5: position fields
00D9F6  1               
00D9F6  1               ; ----------------------------------------------------------------------------
00D9F6  1               ; Recalculate the indexed object state and advance $0595,X again.
00D9F6  1               ; ----------------------------------------------------------------------------
00D9F6  1               
00D9F6  1  20 68 DA         jsr GetCurrentObjectStateIndex
00D9F9  1                                               ; $D9F6: 20 68 DA
00D9F9  1               
00D9F9  1  FE 95 05         inc $0595,x                 ; $D9F9: FE 95 05
00D9FC  1  85 95            sta $95                     ; $D9FC: 85 95
00D9FE  1  D0 06            bne SecondaryObject_RunFrameHelper_DA06
00DA00  1                                               ; $D9FE: D0 06
00DA00  1               
00DA00  1               ; ----------------------------------------------------------------------------
00DA00  1               ; If A is zero, select a delay and wait before continuing.
00DA00  1               ; ----------------------------------------------------------------------------
00DA00  1               SecondaryObject_SelectRetryDelay:
00DA00  1  20 B8 DB         jsr SelectSecondaryObjectDelay                   ; $DA00: 20 B8 DB
00DA03  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $DA03: 20 41 EB
00DA06  1               
00DA06  1               ; ----------------------------------------------------------------------------
00DA06  1               ; Run the per-frame helper, then begin another geometry/region test.
00DA06  1               ; ----------------------------------------------------------------------------
00DA06  1               
00DA06  1               SecondaryObject_RunFrameHelper_DA06: ; $DA06
00DA06  1  20 BC DA         jsr CheckCurrentObjectSelector                   ; $DA06: 20 BC DA
00DA09  1               
00DA09  1  20 B0 E4         jsr UseFixedGeometryRecord54                   ; $DA09: 20 B0 E4
00DA0C  1  20 5F E5         jsr ApplyCurrentObjectGeometry                   ; $DA0C: 20 5F E5
00DA0F  1               
00DA0F  1               ; ============================================================================
00DA0F  1               ; $DA0F-$DA10
00DA0F  1               ; Complete the geometry retry path begun at $DA06.
00DA0F  1               ;
00DA0F  1               ; Carry set returns to $DA00, where a new delay is selected before retrying.
00DA0F  1               ; ============================================================================
00DA0F  1               
00DA0F  1  B0 EF            bcs SecondaryObject_SelectRetryDelay
00DA11  1                                               ; $DA0F: B0 EF
00DA11  1               
00DA11  1               ; ============================================================================
00DA11  1               ; $DA11-$DA24
00DA11  1               ; Wait while the secondary object remains in an active motion/state phase.
00DA11  1               ; ============================================================================
00DA11  1               
00DA11  1               SecondaryObject_WaitForState:   ; $DA11
00DA11  1  20 48 EB         jsr SelectObjectEventBank1                   ; $DA11: 20 48 EB
00DA14  1  20 BC DA         jsr CheckCurrentObjectSelector                   ; $DA14: 20 BC DA
00DA17  1               
00DA17  1               ; ----------------------------------------------------------------------------
00DA17  1               ; SpecialSequenceState or ObjectTransitionState immediately selects the timer path at $DA25.
00DA17  1               ; ----------------------------------------------------------------------------
00DA17  1               
00DA17  1  A5 6D            lda SpecialSequenceState                 ; $DA17: A5 6D
00DA19  1  05 6E            ora ObjectTransitionState                 ; $DA19: 05 6E
00DA1B  1  D0 08            bne SecondaryObject_NegativeResultPath
00DA1D  1                                               ; $DA1B: D0 08
00DA1D  1               
00DA1D  1               ; ----------------------------------------------------------------------------
00DA1D  1               ; Continue waiting while BaseMotionPhase is zero.
00DA1D  1               ; ----------------------------------------------------------------------------
00DA1D  1               
00DA1D  1  A5 5D            lda BaseMotionPhase             ; $DA1D: A5 5D
00DA1F  1  F0 F0            beq SecondaryObject_WaitForState
00DA21  1                                               ; $DA1F: F0 F0
00DA21  1               
00DA21  1               ; ----------------------------------------------------------------------------
00DA21  1               ; Continue waiting while PendingStateTransition is nonzero.
00DA21  1               ; ----------------------------------------------------------------------------
00DA21  1               
00DA21  1  A5 60            lda PendingStateTransition                 ; $DA21: A5 60
00DA23  1  D0 EC            bne SecondaryObject_WaitForState
00DA25  1                                               ; $DA23: D0 EC
00DA25  1               
00DA25  1               ; ============================================================================
00DA25  1               ; $DA25-$DA5E
00DA25  1               ; Shared secondary-object timer and transition path.
00DA25  1               ;
00DA25  1               ; This is the real destination used by several earlier jumps and branches.
00DA25  1               ; ============================================================================
00DA25  1               
00DA25  1               SecondaryObject_NegativeResultPath: ; $DA25
00DA25  1  A6 E1            ldx CurrentObjectIndex      ; $DA25: A6 E1
00DA27  1               
00DA27  1  A9 01            lda #$01                    ; $DA27: A9 01
00DA29  1  9D B1 05         sta $05B1,x                 ; $DA29: 9D B1 05
00DA2C  1               
00DA2C  1               ; ----------------------------------------------------------------------------
00DA2C  1               ; Wait for a frame, process the object, and count down its timer.
00DA2C  1               ; ----------------------------------------------------------------------------
00DA2C  1               
00DA2C  1               SecondaryObject_DA2C_TimerLoop: ; $DA2C
00DA2C  1  20 48 EB         jsr SelectObjectEventBank1                   ; $DA2C: 20 48 EB
00DA2F  1  20 BC DA         jsr CheckCurrentObjectSelector                   ; $DA2F: 20 BC DA
00DA32  1               
00DA32  1  A6 E1            ldx CurrentObjectIndex      ; $DA32: A6 E1
00DA34  1               
00DA34  1  DE B1 05         dec $05B1,x                 ; $DA34: DE B1 05
00DA37  1  D0 10            bne SecondaryObject_DA49_CheckSelector
00DA39  1                                               ; $DA37: D0 10
00DA39  1               
00DA39  1               ; ----------------------------------------------------------------------------
00DA39  1               ; Timer expired. Run the alternate geometry test.
00DA39  1               ; ----------------------------------------------------------------------------
00DA39  1               
00DA39  1  20 9A E4         jsr SelectGeometryRecord_28                   ; $DA39: 20 9A E4
00DA3C  1  20 5F E5         jsr ApplyCurrentObjectGeometry                   ; $DA3C: 20 5F E5
00DA3F  1               
00DA3F  1  90 1B            bcc SecondaryObject_DA5C_ReturnToIndexedPath
00DA41  1                                               ; $DA3F: 90 1B
00DA41  1               
00DA41  1               ; ----------------------------------------------------------------------------
00DA41  1               ; Geometry test remains active.
00DA41  1               ;
00DA41  1               ; Select a new timer value and store it into $05B1,X.
00DA41  1               ; ----------------------------------------------------------------------------
00DA41  1               
00DA41  1  20 B8 DB         jsr SelectSecondaryObjectDelay                   ; $DA41: 20 B8 DB
00DA44  1               
00DA44  1  A6 E1            ldx CurrentObjectIndex      ; $DA44: A6 E1
00DA46  1  9D B1 05         sta $05B1,x                 ; $DA46: 9D B1 05
00DA49  1               
00DA49  1               ; ----------------------------------------------------------------------------
00DA49  1               ; Derive the current selector.
00DA49  1               ;
00DA49  1               ; Selector one, or a nonzero SpecialSequenceState, returns to the timer loop.
00DA49  1               ; ----------------------------------------------------------------------------
00DA49  1               
00DA49  1               SecondaryObject_DA49_CheckSelector: ; $DA49
00DA49  1  20 DC E3         jsr GetCurrentObjectSelectorAndState
00DA4C  1                                               ; $DA49: 20 DC E3
00DA4C  1               
00DA4C  1  C0 01            cpy #$01                    ; $DA4C: C0 01
00DA4E  1  F0 DC            beq SecondaryObject_DA2C_TimerLoop
00DA50  1                                               ; $DA4E: F0 DC
00DA50  1               
00DA50  1  A5 6D            lda SpecialSequenceState                 ; $DA50: A5 6D
00DA52  1  D0 D8            bne SecondaryObject_DA2C_TimerLoop
00DA54  1                                               ; $DA52: D0 D8
00DA54  1               
00DA54  1               ; ----------------------------------------------------------------------------
00DA54  1               ; Continue the timer loop while $DB18 returns carry clear.
00DA54  1               ;
00DA54  1               ; Carry set returns to the timer initialization path at $D8C3.
00DA54  1               ; ----------------------------------------------------------------------------
00DA54  1               
00DA54  1  20 18 DB         jsr TestCurrentObjectInput                   ; $DA54: 20 18 DB
00DA57  1  90 D3            bcc SecondaryObject_DA2C_TimerLoop
00DA59  1                                               ; $DA57: 90 D3
00DA59  1               
00DA59  1  4C C3 D8         jmp SecondaryObject_ActivateTimer
00DA5C  1                                               ; $DA59: 4C C3 D8
00DA5C  1               
00DA5C  1               ; ----------------------------------------------------------------------------
00DA5C  1               ; The alternate geometry test completed.
00DA5C  1               ;
00DA5C  1               ; Return to the indexed-state path at $D967.
00DA5C  1               ; ----------------------------------------------------------------------------
00DA5C  1               
00DA5C  1               SecondaryObject_DA5C_ReturnToIndexedPath: ; $DA5C
00DA5C  1  4C 67 D9         jmp SecondaryObject_AdvanceIndexedState
00DA5F  1                                               ; $DA5C: 4C 67 D9
00DA5F  1               
00DA5F  1               ; ============================================================================
00DA5F  1               ; $DA5F-$DA67
00DA5F  1               ; Convert CurrentObjectIndex into a smaller selector and tail-call $E246.
00DA5F  1               ;
00DA5F  1               ; Calculation:
00DA5F  1               ;
00DA5F  1               ;   Y = (CurrentObjectIndex >> 1) - 1 - !C
00DA5F  1               ;
00DA5F  1               ; The SBC intentionally uses carry left by LSR.
00DA5F  1               ; ============================================================================
00DA5F  1               
00DA5F  1               ; ----------------------------------------------------------------------------
00DA5F  1               ; Contract:
00DA5F  1               ;   Description: Implements Get Current Object Selector.
00DA5F  1               ;   Entry: Registers: A; Memory: currentobjectindex
00DA5F  1               ;   Returns/products: Registers/clobbers: A, Y; Flags: condition flags may carry result state
00DA5F  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00DA5F  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00DA5F  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00DA5F  1               ;          comparison, load, or store path and are not a stable API product.
00DA5F  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 3.
00DA5F  1               ; ----------------------------------------------------------------------------
00DA5F  1               GetCurrentObjectSelector:       ; $DA5F
00DA5F  1  A5 E1            lda CurrentObjectIndex      ; $DA5F: A5 E1
00DA61  1  4A               lsr                         ; $DA61: 4A
00DA62  1               
00DA62  1  E9 01            sbc #$01                    ; $DA62: E9 01
00DA64  1  A8               tay                         ; $DA64: A8
00DA65  1               
00DA65  1  4C 46 E2         jmp FindObjectStateForSelector                   ; $DA65: 4C 46 E2
00DA68  1               
00DA68  1               ; ============================================================================
00DA68  1               ; $DA68-$DA6C
00DA68  1               ; Convert CurrentObjectIndex into an object-state array index.
00DA68  1               ;
00DA68  1               ; Exit:
00DA68  1               ;   A = CurrentObjectIndex >> 1
00DA68  1               ;   X = CurrentObjectIndex >> 1
00DA68  1               ; ============================================================================
00DA68  1               
00DA68  1               GetCurrentObjectStateIndex:     ; $DA68
00DA68  1  A5 E1            lda CurrentObjectIndex      ; $DA68: A5 E1
00DA6A  1  4A               lsr                         ; $DA6A: 4A
00DA6B  1  AA               tax                         ; $DA6B: AA
00DA6C  1               
00DA6C  1  60               rts                         ; $DA6C: 60
00DA6D  1               
00DA6D  1               ; ============================================================================
00DA6D  1               ; $DA6D-$DA80
00DA6D  1               ; Compare the current event selector against the object's derived selector.
00DA6D  1               ;
00DA6D  1               ; When they match, mark the corresponding zero-page object state at $95,X
00DA6D  1               ; as active by storing $01.
00DA6D  1               ; ============================================================================
00DA6D  1               
00DA6D  1               ; ----------------------------------------------------------------------------
00DA6D  1               ; Contract:
00DA6D  1               ;   Description: Implements Mark Matching Object State.
00DA6D  1               ;   Entry: Registers: A, X, Y; Memory: mathtemp05
00DA6D  1               ;   Returns/products: Registers/clobbers: A, X
00DA6D  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00DA6D  1               ;   Memory effects: mathtemp05, $95
00DA6D  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00DA6D  1               ;          comparison, load, or store path and are not a stable API product.
00DA6D  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00DA6D  1               ; ----------------------------------------------------------------------------
00DA6D  1               MarkMatchingObjectState:        ; $DA6D
00DA6D  1  20 DC E3         jsr GetCurrentObjectSelectorAndState
00DA70  1                                               ; $DA6D: 20 DC E3
00DA70  1                                               ; Returns an event/object selector in X and Y.
00DA70  1               
00DA70  1  8A               txa                         ; $DA70: 8A
00DA71  1  38               sec                         ; $DA71: 38
00DA72  1  E9 06            sbc #$06                    ; $DA72: E9 06
00DA74  1  85 05            sta MathTemp05              ; $DA74: 85 05
00DA76  1               
00DA76  1  C4 05            cpy MathTemp05              ; $DA76: C4 05
00DA78  1  D0 06            bne MarkMatchingObjectState_Return
00DA7A  1                                               ; $DA78: D0 06
00DA7A  1               
00DA7A  1               ; ----------------------------------------------------------------------------
00DA7A  1               ; The selectors match.
00DA7A  1               ;
00DA7A  1               ; Convert A to the corresponding indexed state slot and set $95,X to one.
00DA7A  1               ; ----------------------------------------------------------------------------
00DA7A  1               
00DA7A  1  4A               lsr                         ; $DA7A: 4A
00DA7B  1  AA               tax                         ; $DA7B: AA
00DA7C  1               
00DA7C  1  A9 01            lda #$01                    ; $DA7C: A9 01
00DA7E  1  95 95            sta $95,x                   ; $DA7E: 95 95
00DA80  1               
00DA80  1               MarkMatchingObjectState_Return: ; $DA80
00DA80  1  60               rts                         ; $DA80: 60
00DA81  1               
00DA81  1               ; ============================================================================
00DA81  1               ; $DA81-$DA9B
00DA81  1               ; Update the current object's animation and sprite-state values.
00DA81  1               ;
00DA81  1               ; This routine:
00DA81  1               ;   1. Updates the object through $E6B7.
00DA81  1               ;   2. Derives an event selector through GetCurrentObjectSelectorAndState.
00DA81  1               ;   3. Converts Y and X to compact table indices.
00DA81  1               ;   4. Stores table-selected values into $03B0,X and $039B,X.
00DA81  1               ;
00DA81  1               ; The table loads intentionally use bases one byte before the visible tables:
00DA81  1               ;
00DA81  1               ;   $DA9B,Y
00DA81  1               ;   $DA9F,Y
00DA81  1               ; ============================================================================
00DA81  1               
00DA81  1               UpdateCurrentObjectAnimation:   ; $DA81
00DA81  1  A6 E1            ldx CurrentObjectIndex      ; $DA81: A6 E1
00DA83  1  20 B7 E6         jsr ClearMovementTransforms                   ; $DA83: 20 B7 E6
00DA86  1               
00DA86  1  20 DC E3         jsr GetCurrentObjectSelectorAndState
00DA89  1                                               ; $DA86: 20 DC E3
00DA89  1               
00DA89  1               ; ----------------------------------------------------------------------------
00DA89  1               ; Convert the Y selector to a four-entry table index.
00DA89  1               ; ----------------------------------------------------------------------------
00DA89  1               
00DA89  1  98               tya                         ; $DA89: 98
00DA8A  1  4A               lsr                         ; $DA8A: 4A
00DA8B  1  A8               tay                         ; $DA8B: A8
00DA8C  1               
00DA8C  1               ; ----------------------------------------------------------------------------
00DA8C  1               ; Convert the X selector to its sprite-array index.
00DA8C  1               ; ----------------------------------------------------------------------------
00DA8C  1               
00DA8C  1  8A               txa                         ; $DA8C: 8A
00DA8D  1  4A               lsr                         ; $DA8D: 4A
00DA8E  1  AA               tax                         ; $DA8E: AA
00DA8F  1               
00DA8F  1               ; ----------------------------------------------------------------------------
00DA8F  1               ; Load the table-selected animation values.
00DA8F  1               ;
00DA8F  1               ; The first table access uses base $DA9B, where byte $DA9B is the preceding
00DA8F  1               ; RTS opcode. Expected Y values begin at one.
00DA8F  1               ; ----------------------------------------------------------------------------
00DA8F  1               
00DA8F  1  B9 9B DA         lda $DA9B,y                 ; $DA8F: B9 9B DA
00DA92  1  9D B0 03         sta $03B0,x                 ; $DA92: 9D B0 03
00DA95  1               
00DA95  1  B9 9F DA         lda $DA9F,y                 ; $DA95: B9 9F DA
00DA98  1  9D 9B 03         sta $039B,x                 ; $DA98: 9D 9B 03
00DA9B  1               
00DA9B  1  60               rts                         ; $DA9B: 60
00DA9C  1               
00DA9C  1               ; ============================================================================
00DA9C  1               ; $DA9C-$DAA3
00DA9C  1               ; Parallel four-byte animation lookup tables.
00DA9C  1               ;
00DA9C  1               ; Because the code uses one-byte-earlier bases, expected Y values are $01-$04:
00DA9C  1               ;
00DA9C  1               ;   LDA $DA9B,Y:
00DA9C  1               ;       Y=$01 -> $DA9C
00DA9C  1               ;       Y=$04 -> $DA9F
00DA9C  1               ;
00DA9C  1               ;   LDA $DA9F,Y:
00DA9C  1               ;       Y=$01 -> $DAA0
00DA9C  1               ;       Y=$04 -> $DAA3
00DA9C  1               ; ============================================================================
00DA9C  1               
00DA9C  1               ObjectAnimationAttributeTable:  ; $DA9C
00DA9C  1  1D 1D 1A 7A      .byte $1D,$1D,$1A,$7A
00DAA0  1               
00DAA0  1               ObjectAnimationFrameTable:      ; $DAA0
00DAA0  1  53 56 4D 7A      .byte $53,$56,$4D,$7A
00DAA4  1               
00DAA4  1               ; ============================================================================
00DAA4  1               ; $DAA4-$DABB
00DAA4  1               ; Count matching object-state entries.
00DAA4  1               ;
00DAA4  1               ; The selector returned by GetCurrentObjectSelectorAndState is compared against the four entries at
00DAA4  1               ; $0598-$059B. Carry is set on return when at least two entries match.
00DAA4  1               ;
00DAA4  1               ; Return:
00DAA4  1               ;   Y = number of matching entries
00DAA4  1               ;   C = set when Y >= 2
00DAA4  1               ; ============================================================================
00DAA4  1               
00DAA4  1               ; ----------------------------------------------------------------------------
00DAA4  1               ; Contract:
00DAA4  1               ;   Description: Implements Count Matching Object States.
00DAA4  1               ;   Entry: Registers: A, X, Y; Memory: $0598
00DAA4  1               ;   Returns/products: Registers/clobbers: A, X, Y; Flags: condition flags may carry result state
00DAA4  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00DAA4  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00DAA4  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00DAA4  1               ;          comparison, load, or store path and are not a stable API product.
00DAA4  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 2.
00DAA4  1               ; ----------------------------------------------------------------------------
00DAA4  1               CountMatchingObjectStates:      ; $DAA4
00DAA4  1  20 DC E3         jsr GetCurrentObjectSelectorAndState
00DAA7  1                                               ; $DAA4: 20 DC E3
00DAA7  1               
00DAA7  1  98               tya                         ; $DAA7: 98
00DAA8  1  30 2B            bmi FinishSecondaryObject   ; $DAA8: 30 2B
00DAAA  1               
00DAAA  1               ; ----------------------------------------------------------------------------
00DAAA  1               ; Count entries in $0598-$059B that equal A.
00DAAA  1               ; ----------------------------------------------------------------------------
00DAAA  1               
00DAAA  1  A0 00            ldy #$00                    ; $DAAA: A0 00
00DAAC  1  A2 03            ldx #$03                    ; $DAAC: A2 03
00DAAE  1               
00DAAE  1               CountMatchingObjectStates_Loop: ; $DAAE
00DAAE  1  DD 98 05         cmp $0598,x                 ; $DAAE: DD 98 05
00DAB1  1  D0 01            bne CountMatchingObjectStates_Next
00DAB3  1                                               ; $DAB1: D0 01
00DAB3  1               
00DAB3  1  C8               iny                         ; $DAB3: C8
00DAB4  1               
00DAB4  1               CountMatchingObjectStates_Next: ; $DAB4
00DAB4  1  CA               dex                         ; $DAB4: CA
00DAB5  1  10 F7            bpl CountMatchingObjectStates_Loop
00DAB7  1                                               ; $DAB5: 10 F7
00DAB7  1               
00DAB7  1  C0 02            cpy #$02                    ; $DAB7: C0 02
00DAB9  1  B0 08            bcs DisableCurrentObject    ; $DAB9: B0 08
00DABB  1               
00DABB  1  60               rts                         ; $DABB: 60
00DABC  1               
00DABC  1               ; ============================================================================
00DABC  1               ; $DABC-$DAC2
00DABC  1               ; Check whether the selector returned by GetCurrentObjectSelectorAndState is negative.
00DABC  1               ;
00DABC  1               ; Return:
00DABC  1               ;   N flag reflects the selector sign.
00DABC  1               ;
00DABC  1               ; A negative selector transfers to the common secondary-object finish path.
00DABC  1               ; ============================================================================
00DABC  1               
00DABC  1               ; ----------------------------------------------------------------------------
00DABC  1               ; Contract:
00DABC  1               ;   Description: Implements Check Current Object Selector.
00DABC  1               ;   Entry: Registers: Y
00DABC  1               ;   Returns/products: Registers/clobbers: A
00DABC  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00DABC  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00DABC  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00DABC  1               ;          comparison, load, or store path and are not a stable API product.
00DABC  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 6.
00DABC  1               ; ----------------------------------------------------------------------------
00DABC  1               CheckCurrentObjectSelector:     ; $DABC
00DABC  1  20 DC E3         jsr GetCurrentObjectSelectorAndState
00DABF  1                                               ; $DABC: 20 DC E3
00DABF  1               
00DABF  1  98               tya                         ; $DABF: 98
00DAC0  1  30 13            bmi FinishSecondaryObject   ; $DAC0: 30 13
00DAC2  1               
00DAC2  1  60               rts                         ; $DAC2: 60
00DAC3  1               
00DAC3  1               ; ============================================================================
00DAC3  1               ; $DAC3-$DAD4
00DAC3  1               ; Disable the current object and advance the associated state sequence.
00DAC3  1               ;
00DAC3  1               ; This path is entered when at least two object-state entries match.
00DAC3  1               ; ============================================================================
00DAC3  1               
00DAC3  1               DisableCurrentObject:           ; $DAC3
00DAC3  1  20 DC E3         jsr GetCurrentObjectSelectorAndState                   ; $DAC3: 20 DC E3
00DAC6  1               
00DAC6  1  98               tya                         ; $DAC6: 98
00DAC7  1  4A               lsr                         ; $DAC7: 4A
00DAC8  1               ; ----------------------------------------------------------------------------
00DAC8  1               ; Contract:
00DAC8  1               ;   Description: Internal state-routing entry that stores A as the state selector.
00DAC8  1               ;   Entry: A = state selector.
00DAC8  1               ;   Returns/products: StateSelector updated; returns through parent routine flow.
00DAC8  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00DAC8  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00DAC8  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00DAC8  1               ;          comparison, load, or store path and are not a stable API product.
00DAC8  1               ;   Validation: Internal-entry contract; call sites: internal entry.
00DAC8  1               ; ----------------------------------------------------------------------------
00DAC8  1               StoreStateSelector:
00DAC8  1  85 72            sta StateSelector ; $DAC8: 85 72
00DACA  1               
00DACA  1  20 68 DA         jsr GetCurrentObjectStateIndex
00DACD  1                                               ; $DACA: 20 68 DA
00DACD  1               
00DACD  1  A9 FF            lda #$FF                    ; $DACD: A9 FF
00DACF  1  9D 95 05         sta $0595,x                 ; $DACF: 9D 95 05
00DAD2  1               
00DAD2  1  20 E4 CC         jsr AdvanceAlternateStateSequence
00DAD5  1                                               ; $DAD2: 20 E4 CC
00DAD5  1               
00DAD5  1               ; ============================================================================
00DAD5  1               ; $DAD5-$DAEA
00DAD5  1               ; Finish the current secondary-object sequence.
00DAD5  1               ;
00DAD5  1               ; This path:
00DAD5  1               ;   1. Calls the engine helper at $E2D3.
00DAD5  1               ;   2. Waits $1E ticks.
00DAD5  1               ;   3. Sets the current object's animation fields to $7A.
00DAD5  1               ;   4. Leaves through the common engine exit.
00DAD5  1               ; ============================================================================
00DAD5  1               
00DAD5  1               FinishSecondaryObject:          ; $DAD5
00DAD5  1  20 D3 E2         jsr ClearCurrentObjectMovement                   ; $DAD5: 20 D3 E2
00DAD8  1               
00DAD8  1  A9 1E            lda #$1E                    ; $DAD8: A9 1E
00DADA  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $DADA: 20 41 EB
00DADD  1               
00DADD  1  20 68 DA         jsr GetCurrentObjectStateIndex
00DAE0  1                                               ; $DADD: 20 68 DA
00DAE0  1               
00DAE0  1  A9 7A            lda #$7A                    ; $DAE0: A9 7A
00DAE2  1  9D B0 03         sta $03B0,x                 ; $DAE2: 9D B0 03
00DAE5  1  9D 9B 03         sta $039B,x                 ; $DAE5: 9D 9B 03
00DAE8  1               
00DAE8  1  4C 6A EB         jmp CommonEngineExit                   ; $DAE8: 4C 6A EB
00DAEB  1               
00DAEB  1               ; ============================================================================
00DAEB  1               ; $DAEB-$DAF6
00DAEB  1               ; Store the current selector in the object-state mirror array.
00DAEB  1               ;
00DAEB  1               ; When TrajectoryEvaluationEnabled is zero, GetCurrentObjectSelectorAndState returns a selector:
00DAEB  1               ;
00DAEB  1               ;   X = destination index
00DAEB  1               ;   Y = selector value
00DAEB  1               ;
00DAEB  1               ; The selector is stored at $9B,X.
00DAEB  1               ; ============================================================================
00DAEB  1               
00DAEB  1               ; ----------------------------------------------------------------------------
00DAEB  1               ; Contract:
00DAEB  1               ;   Description: Implements Store Current Object Selector.
00DAEB  1               ;   Entry: Registers: A, Y; Memory: trajectoryevaluationenabled
00DAEB  1               ;   Returns/products: Registers/clobbers: A, X
00DAEB  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00DAEB  1               ;   Memory effects: $9b
00DAEB  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00DAEB  1               ;          comparison, load, or store path and are not a stable API product.
00DAEB  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 3.
00DAEB  1               ; ----------------------------------------------------------------------------
00DAEB  1               StoreCurrentObjectSelector:     ; $DAEB
00DAEB  1  A5 86            lda TrajectoryEvaluationEnabled                 ; $DAEB: A5 86
00DAED  1  D0 07            bne StoreCurrentObjectSelector_Return
00DAEF  1                                               ; $DAED: D0 07
00DAEF  1               
00DAEF  1  20 DC E3         jsr GetCurrentObjectSelectorAndState                   ; $DAEF: 20 DC E3
00DAF2  1               
00DAF2  1  AA               tax                         ; $DAF2: AA
00DAF3  1  98               tya                         ; $DAF3: 98
00DAF4  1               
00DAF4  1  95 9B            sta $9B,x                   ; $DAF4: 95 9B
00DAF6  1               
00DAF6  1               StoreCurrentObjectSelector_Return: ; $DAF6
00DAF6  1  60               rts                         ; $DAF6: 60
00DAF7  1               
00DAF7  1               ; ============================================================================
00DAF7  1               ; $DAF7-$DB17
00DAF7  1               ; Compare the current selector against $9E and update the indexed object state.
00DAF7  1               ;
00DAF7  1               ; This routine can:
00DAF7  1               ;
00DAF7  1               ;   - finish the current object sequence,
00DAF7  1               ;   - disable an object and advance state,
00DAF7  1               ;   - decrement $0595,X,
00DAF7  1               ;   - or increment $0595,X.
00DAF7  1               ; ============================================================================
00DAF7  1               
00DAF7  1               ; ----------------------------------------------------------------------------
00DAF7  1               ; Contract:
00DAF7  1               ;   Description: Updates Current Object Selector State.
00DAF7  1               ;   Entry: Registers: A, Y; Memory: $9e, objecttransitionstate
00DAF7  1               ;   Returns/products: Registers/clobbers: A, Y; Flags: condition flags may carry result state
00DAF7  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00DAF7  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00DAF7  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00DAF7  1               ;          comparison, load, or store path and are not a stable API product.
00DAF7  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 3.
00DAF7  1               ; ----------------------------------------------------------------------------
00DAF7  1               UpdateCurrentObjectSelectorState: ; $DAF7
00DAF7  1  20 DC E3         jsr GetCurrentObjectSelectorAndState                   ; $DAF7: 20 DC E3
00DAFA  1               
00DAFA  1  98               tya                         ; $DAFA: 98
00DAFB  1  30 D8            bmi FinishSecondaryObject   ; $DAFB: 30 D8
00DAFD  1               
00DAFD  1               ; ----------------------------------------------------------------------------
00DAFD  1               ; Compare half of the selector against $9E.
00DAFD  1               ; ----------------------------------------------------------------------------
00DAFD  1               
00DAFD  1  4A               lsr                         ; $DAFD: 4A
00DAFE  1  C5 9E            cmp $9E                     ; $DAFE: C5 9E
00DB00  1  D0 15            bne UpdateCurrentObjectSelectorState_Return
00DB02  1                                               ; $DB00: D0 15
00DB02  1               
00DB02  1               ; ----------------------------------------------------------------------------
00DB02  1               ; If ObjectTransitionState is zero, branch directly into DisableCurrentObject after the
00DB02  1               ; selector-to-index conversion at $DAC3.
00DB02  1               ;
00DB02  1               ; The target $DAC8 stores the current A value into StateSelector.
00DB02  1               ; ----------------------------------------------------------------------------
00DB02  1               
00DB02  1  A4 6E            ldy ObjectTransitionState                 ; $DB02: A4 6E
00DB04  1  F0 C2            beq StoreStateSelector
00DB06  1                                               ; $DB04: F0 C2
00DB06  1               
00DB06  1               ; ----------------------------------------------------------------------------
00DB06  1               ; Decrement the indexed object state and evaluate the current result.
00DB06  1               ; ----------------------------------------------------------------------------
00DB06  1               
00DB06  1  20 68 DA         jsr GetCurrentObjectStateIndex
00DB09  1                                               ; $DB06: 20 68 DA
00DB09  1               
00DB09  1  DE 95 05         dec $0595,x                 ; $DB09: DE 95 05
00DB0C  1               
00DB0C  1  20 5F DA         jsr GetCurrentObjectSelector
00DB0F  1                                               ; $DB0C: 20 5F DA
00DB0F  1               
00DB0F  1  10 B2            bpl DisableCurrentObject    ; $DB0F: 10 B2
00DB11  1               
00DB11  1               ; ----------------------------------------------------------------------------
00DB11  1               ; A negative selector result restores the indexed object-state value.
00DB11  1               ; ----------------------------------------------------------------------------
00DB11  1               
00DB11  1  20 68 DA         jsr GetCurrentObjectStateIndex
00DB14  1                                               ; $DB11: 20 68 DA
00DB14  1               
00DB14  1  FE 95 05         inc $0595,x                 ; $DB14: FE 95 05
00DB17  1               
00DB17  1               UpdateCurrentObjectSelectorState_Return: ; $DB17
00DB17  1  60               rts                         ; $DB17: 60
00DB18  1               
00DB18  1               
00DB18  1               ; ============================================================================
00DB18  1               ; $DB18-$DB2D
00DB18  1               ; Test the current input against a selector-specific mask.
00DB18  1               ;
00DB18  1               ; Return behavior:
00DB18  1               ;
00DB18  1               ;   ActionSequenceCounter == 0:
00DB18  1               ;       A = 0
00DB18  1               ;       returns after ASL
00DB18  1               ;
00DB18  1               ;   DerivedControl0 == 0:
00DB18  1               ;       transfers directly to the next routine at $DB2E
00DB18  1               ;
00DB18  1               ;   InputState1 & InputMaskTable[Y] == 0:
00DB18  1               ;       A = 0
00DB18  1               ;       returns after ASL
00DB18  1               ;
00DB18  1               ;   InputState1 & InputMaskTable[Y] != 0:
00DB18  1               ;       A = InputAux1 << 1
00DB18  1               ;       returns with flags from ASL
00DB18  1               ;
00DB18  1               ; Callers commonly test the N or C flags produced by the final ASL.
00DB18  1               ; ============================================================================
00DB18  1               
00DB18  1               ; ----------------------------------------------------------------------------
00DB18  1               ; Contract:
00DB18  1               ;   Description: Implements Test Current Object Input.
00DB18  1               ;   Entry: Registers: A; Memory: actionsequencecounter, derivedcontrol0, inputstate1, inputmasktable, inputaux1
00DB18  1               ;   Returns/products: Registers/clobbers: A; Flags: condition flags may carry result state
00DB18  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00DB18  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00DB18  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00DB18  1               ;          comparison, load, or store path and are not a stable API product.
00DB18  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 5.
00DB18  1               ; ----------------------------------------------------------------------------
00DB18  1               TestCurrentObjectInput:         ; $DB18
00DB18  1  A5 7E            lda ActionSequenceCounter         ; $DB18: A5 7E
00DB1A  1  F0 10            beq TestCurrentObjectInput_Shift
00DB1C  1                                               ; $DB1A: F0 10
00DB1C  1               
00DB1C  1  A5 0F            lda DerivedControl0         ; $DB1C: A5 0F
00DB1E  1  F0 0E            beq CurrentObjectInputFallback
00DB20  1                                               ; $DB1E: F0 0E
00DB20  1                                               ; Branches to $DB2E, the next routine entry.
00DB20  1               
00DB20  1               ; ----------------------------------------------------------------------------
00DB20  1               ; Obtain the current object/event selector in Y.
00DB20  1               ; ----------------------------------------------------------------------------
00DB20  1               
00DB20  1  20 DC E3         jsr GetCurrentObjectSelectorAndState                   ; $DB20: 20 DC E3
00DB23  1               
00DB23  1               ; ----------------------------------------------------------------------------
00DB23  1               ; Test InputState1 against the selector-specific mask at $DBB0,Y.
00DB23  1               ; ----------------------------------------------------------------------------
00DB23  1               
00DB23  1  A5 13            lda InputState1             ; $DB23: A5 13
00DB25  1  39 B0 DB         and InputMaskTable,y        ; $DB25: 39 B0 DB
00DB28  1               
00DB28  1  F0 02            beq TestCurrentObjectInput_Shift
00DB2A  1                                               ; $DB28: F0 02
00DB2A  1               
00DB2A  1               ; ----------------------------------------------------------------------------
00DB2A  1               ; Matching input was detected. Return InputAux1 shifted left once.
00DB2A  1               ; ----------------------------------------------------------------------------
00DB2A  1               
00DB2A  1  A5 17            lda InputAux1               ; $DB2A: A5 17
00DB2C  1               
00DB2C  1               TestCurrentObjectInput_Shift:   ; $DB2C
00DB2C  1  0A               asl                         ; $DB2C: 0A
00DB2D  1  60               rts                         ; $DB2D: 60
00DB2E  1               
00DB2E  1               ; ============================================================================
00DB2E  1               ; $DB2E-$DB83
00DB2E  1               ; Resolve the current object's input/collision state.
00DB2E  1               ;
00DB2E  1               ; This routine combines:
00DB2E  1               ;   - current object identity,
00DB2E  1               ;   - object-state entries,
00DB2E  1               ;   - animation state,
00DB2E  1               ;   - current selector,
00DB2E  1               ;   - movement state,
00DB2E  1               ;   - coordinate comparisons,
00DB2E  1               ;   - and the region test at $DB84.
00DB2E  1               ;
00DB2E  1               ; Return conventions:
00DB2E  1               ;
00DB2E  1               ;   Carry set:
00DB2E  1               ;       successful or active condition
00DB2E  1               ;
00DB2E  1               ;   Carry clear, A = $00:
00DB2E  1               ;       failed coordinate/region condition
00DB2E  1               ;
00DB2E  1               ;   Carry clear, A = $80:
00DB2E  1               ;       alternate inactive/result condition
00DB2E  1               ;
00DB2E  1               ;   Carry clear, A preserved:
00DB2E  1               ;       neutral state via $DB82
00DB2E  1               ; ============================================================================
00DB2E  1               
00DB2E  1               CurrentObjectInputFallback:     ; $DB2E
00DB2E  1  A6 E1            ldx CurrentObjectIndex      ; $DB2E: A6 E1
00DB30  1               
00DB30  1               ; ----------------------------------------------------------------------------
00DB30  1               ; Special-case object offset $08.
00DB30  1               ; ----------------------------------------------------------------------------
00DB30  1               
00DB30  1  E0 08            cpx #$08                    ; $DB30: E0 08
00DB32  1  D0 12            bne ResolveCurrentObjectSelector
00DB34  1                                               ; $DB32: D0 12
00DB34  1               
00DB34  1  AD 9A 05         lda $059A                   ; $DB34: AD 9A 05
00DB37  1  10 0D            bpl ResolveCurrentObjectSelector
00DB39  1                                               ; $DB37: 10 0D
00DB39  1               
00DB39  1  AD B7 03         lda $03B7                   ; $DB39: AD B7 03
00DB3C  1  C9 0D            cmp #$0D                    ; $DB3C: C9 0D
00DB3E  1  D0 06            bne ResolveCurrentObjectSelector
00DB40  1                                               ; $DB3E: D0 06
00DB40  1               
00DB40  1               ; ----------------------------------------------------------------------------
00DB40  1               ; When object $08 is inactive and frame $03B7 equals $0D, use a random result.
00DB40  1               ;
00DB40  1               ; A zero random result returns through the alternate result at $DB7E.
00DB40  1               ; ----------------------------------------------------------------------------
00DB40  1               
00DB40  1  20 F5 E5         jsr AdvanceRandomState                   ; $DB40: 20 F5 E5
00DB43  1  A8               tay                         ; $DB43: A8
00DB44  1  F0 38            beq ResolveCurrentObject_AlternateResult
00DB46  1                                               ; $DB44: F0 38
00DB46  1               
00DB46  1               ; ----------------------------------------------------------------------------
00DB46  1               ; Derive the current object/event selector.
00DB46  1               ; ----------------------------------------------------------------------------
00DB46  1               
00DB46  1               ResolveCurrentObjectSelector:   ; $DB46
00DB46  1  20 DC E3         jsr GetCurrentObjectSelectorAndState                   ; $DB46: 20 DC E3
00DB49  1               
00DB49  1  98               tya                         ; $DB49: 98
00DB4A  1  4A               lsr                         ; $DB4A: 4A
00DB4B  1               
00DB4B  1               ; ----------------------------------------------------------------------------
00DB4B  1               ; If half the selector equals $BB, use the secondary region-test path.
00DB4B  1               ; ----------------------------------------------------------------------------
00DB4B  1               
00DB4B  1  C5 BB            cmp $BB                     ; $DB4B: C5 BB
00DB4D  1  F0 2A            beq ResolveCurrentObject_SecondaryRegion
00DB4F  1                                               ; $DB4D: F0 2A
00DB4F  1               
00DB4F  1               ; ----------------------------------------------------------------------------
00DB4F  1               ; BaseMotionPhase equal to zero returns through the neutral carry-clear path.
00DB4F  1               ; ----------------------------------------------------------------------------
00DB4F  1               
00DB4F  1  A5 5D            lda BaseMotionPhase             ; $DB4F: A5 5D
00DB51  1  F0 2F            beq ResolveCurrentObject_Neutral
00DB53  1                                               ; $DB51: F0 2F
00DB53  1               
00DB53  1               ; ----------------------------------------------------------------------------
00DB53  1               ; BaseMotionEventCount equal to zero returns the alternate $80 result.
00DB53  1               ; ----------------------------------------------------------------------------
00DB53  1               
00DB53  1  A5 5E            lda BaseMotionEventCount        ; $DB53: A5 5E
00DB55  1  F0 27            beq ResolveCurrentObject_AlternateResult
00DB57  1                                               ; $DB55: F0 27
00DB57  1               
00DB57  1               ; ----------------------------------------------------------------------------
00DB57  1               ; A negative current-object selector returns through the neutral path.
00DB57  1               ; ----------------------------------------------------------------------------
00DB57  1               
00DB57  1  20 5F DA         jsr GetCurrentObjectSelector
00DB5A  1                                               ; $DB57: 20 5F DA
00DB5A  1               
00DB5A  1  30 26            bmi ResolveCurrentObject_Neutral
00DB5C  1                                               ; $DB5A: 30 26
00DB5C  1               
00DB5C  1               ; ----------------------------------------------------------------------------
00DB5C  1               ; Run the region test at $DB84.
00DB5C  1               ;
00DB5C  1               ; Carry clear selects the zero-result path at $DB75.
00DB5C  1               ; ----------------------------------------------------------------------------
00DB5C  1               
00DB5C  1  20 84 DB         jsr TestCurrentObjectRegion ; $DB5C: 20 84 DB
00DB5F  1  90 14            bcc ResolveCurrentObject_ZeroResult
00DB61  1                                               ; $DB5F: 90 14
00DB61  1               
00DB61  1               ; ----------------------------------------------------------------------------
00DB61  1               ; Compare the current object's high X coordinate against a selector-indexed
00DB61  1               ; threshold table at $E021,Y.
00DB61  1               ; ----------------------------------------------------------------------------
00DB61  1               
00DB61  1  20 DC E3         jsr GetCurrentObjectSelectorAndState                   ; $DB61: 20 DC E3
00DB64  1               
00DB64  1  98               tya                         ; $DB64: 98
00DB65  1  4A               lsr                         ; $DB65: 4A
00DB66  1  A8               tay                         ; $DB66: A8
00DB67  1               
00DB67  1  BD 0A 05         lda $050A,x                 ; $DB67: BD 0A 05
00DB6A  1  D9 21 E0         cmp $E021,y                 ; $DB6A: D9 21 E0
00DB6D  1               
00DB6D  1               ; ----------------------------------------------------------------------------
00DB6D  1               ; Convert comparison carry, selector range, and ADC carry into one final test.
00DB6D  1               ; ----------------------------------------------------------------------------
00DB6D  1               
00DB6D  1  2A               rol                         ; $DB6D: 2A
00DB6E  1               
00DB6E  1  C0 03            cpy #$03                    ; $DB6E: C0 03
00DB70  1  69 00            adc #$00                    ; $DB70: 69 00
00DB72  1               
00DB72  1  4A               lsr                         ; $DB72: 4A
00DB73  1  90 09            bcc ResolveCurrentObject_AlternateResult
00DB75  1                                               ; $DB73: 90 09
00DB75  1               
00DB75  1               ; ----------------------------------------------------------------------------
00DB75  1               ; Return carry clear with A = $00.
00DB75  1               ; ----------------------------------------------------------------------------
00DB75  1               
00DB75  1               ResolveCurrentObject_ZeroResult: ; $DB75
00DB75  1  38               sec                         ; $DB75: 38
00DB76  1  A9 00            lda #$00                    ; $DB76: A9 00
00DB78  1  60               rts                         ; $DB78: 60
00DB79  1                                               ; LDA preserves carry set, despite the path
00DB79  1                                               ; name. Callers may rely on both A and carry.
00DB79  1               
00DB79  1               ; ----------------------------------------------------------------------------
00DB79  1               ; Secondary region-test path.
00DB79  1               ;
00DB79  1               ; Carry clear returns A = $00 with carry set through $DB75.
00DB79  1               ; Carry set falls through to the alternate $80 result.
00DB79  1               ; ----------------------------------------------------------------------------
00DB79  1               
00DB79  1               ResolveCurrentObject_SecondaryRegion: ; $DB79
00DB79  1  20 84 DB         jsr TestCurrentObjectRegion ; $DB79: 20 84 DB
00DB7C  1  90 F7            bcc ResolveCurrentObject_ZeroResult
00DB7E  1                                               ; $DB7C: 90 F7
00DB7E  1               
00DB7E  1               ; ----------------------------------------------------------------------------
00DB7E  1               ; Return carry clear with A = $80.
00DB7E  1               ; ----------------------------------------------------------------------------
00DB7E  1               
00DB7E  1               ResolveCurrentObject_AlternateResult: ; $DB7E
00DB7E  1  18               clc                         ; $DB7E: 18
00DB7F  1  A9 80            lda #$80                    ; $DB7F: A9 80
00DB81  1  60               rts                         ; $DB81: 60
00DB82  1               
00DB82  1               ; ----------------------------------------------------------------------------
00DB82  1               ; Neutral return with carry clear. A is preserved from the preceding test.
00DB82  1               ; ----------------------------------------------------------------------------
00DB82  1               
00DB82  1               ResolveCurrentObject_Neutral:   ; $DB82
00DB82  1  18               clc                         ; $DB82: 18
00DB83  1  60               rts                         ; $DB83: 60
00DB84  1               
00DB84  1               ; ============================================================================
00DB84  1               ; $DB84-$DBAF
00DB84  1               ; Test whether another active object satisfies a selector and state condition
00DB84  1               ; relative to CurrentObjectIndex.
00DB84  1               ;
00DB84  1               ; Return:
00DB84  1               ;   Carry is the primary Boolean result.
00DB84  1               ;
00DB84  1               ;   C = 1:
00DB84  1               ;       matching/active condition
00DB84  1               ;
00DB84  1               ;   C = 0:
00DB84  1               ;       no matching condition
00DB84  1               ;
00DB84  1               ; The final LSR converts bit zero of the calculated value into carry.
00DB84  1               ; ============================================================================
00DB84  1               
00DB84  1               ; ----------------------------------------------------------------------------
00DB84  1               ; Contract:
00DB84  1               ;   Description: Implements Test Current Object Region.
00DB84  1               ;   Entry: Registers: A, X, Y; Memory: $0598, currentobjectindex, $056d
00DB84  1               ;   Returns/products: Registers/clobbers: A, X, Y; Flags: condition flags may carry result state
00DB84  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00DB84  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00DB84  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00DB84  1               ;          comparison, load, or store path and are not a stable API product.
00DB84  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 2.
00DB84  1               ; ----------------------------------------------------------------------------
00DB84  1               TestCurrentObjectRegion:        ; $DB84
00DB84  1  20 DC E3         jsr GetCurrentObjectSelectorAndState                   ; $DB84: 20 DC E3
00DB87  1                                               ; Returns a selector in Y.
00DB87  1               
00DB87  1               ; ----------------------------------------------------------------------------
00DB87  1               ; Convert the selector into a comparison value:
00DB87  1               ;
00DB87  1               ;   A = ((Y >> 1) << 1) + 3
00DB87  1               ;
00DB87  1               ; The LSR/ASL pair clears bit zero before adding three.
00DB87  1               ; Carry from ASL is intentionally retained by ADC.
00DB87  1               ; ----------------------------------------------------------------------------
00DB87  1               
00DB87  1  98               tya                         ; $DB87: 98
00DB88  1  4A               lsr                         ; $DB88: 4A
00DB89  1  0A               asl                         ; $DB89: 0A
00DB8A  1  69 03            adc #$03                    ; $DB8A: 69 03
00DB8C  1               
00DB8C  1               ; ----------------------------------------------------------------------------
00DB8C  1               ; Search the four state entries $0598-$059B.
00DB8C  1               ;
00DB8C  1               ; X starts at four, is decremented before each comparison, and stops when A is
00DB8C  1               ; greater than or equal to the indexed state value.
00DB8C  1               ; ----------------------------------------------------------------------------
00DB8C  1               
00DB8C  1  A2 04            ldx #$04                    ; $DB8C: A2 04
00DB8E  1               
00DB8E  1               TestCurrentObjectRegion_Search: ; $DB8E
00DB8E  1  CA               dex                         ; $DB8E: CA
00DB8F  1               
00DB8F  1  DD 98 05         cmp $0598,x                 ; $DB8F: DD 98 05
00DB92  1  90 FA            bcc TestCurrentObjectRegion_Search
00DB94  1                                               ; $DB92: 90 FA
00DB94  1               
00DB94  1               ; ----------------------------------------------------------------------------
00DB94  1               ; Load the selected state entry into Y.
00DB94  1               ;
00DB94  1               ; Values of eight or greater return immediately. Carry remains set from
00DB94  1               ; CPY #$08 in that case.
00DB94  1               ; ----------------------------------------------------------------------------
00DB94  1               
00DB94  1  BC 98 05         ldy $0598,x                 ; $DB94: BC 98 05
00DB97  1               
00DB97  1  C0 08            cpy #$08                    ; $DB97: C0 08
00DB99  1  B0 14            bcs TestCurrentObjectRegion_Return
00DB9B  1                                               ; $DB99: B0 14
00DB9B  1               
00DB9B  1               ; ----------------------------------------------------------------------------
00DB9B  1               ; Convert the state-table index into an object offset:
00DB9B  1               ;
00DB9B  1               ;   A = (X * 2) + 6
00DB9B  1               ;
00DB9B  1               ; If this offset is the current object, return immediately. Carry is set by
00DB9B  1               ; CMP on equality.
00DB9B  1               ; ----------------------------------------------------------------------------
00DB9B  1               
00DB9B  1  8A               txa                         ; $DB9B: 8A
00DB9C  1  0A               asl                         ; $DB9C: 0A
00DB9D  1  69 06            adc #$06                    ; $DB9D: 69 06
00DB9F  1               
00DB9F  1  C5 E1            cmp CurrentObjectIndex      ; $DB9F: C5 E1
00DBA1  1  F0 0C            beq TestCurrentObjectRegion_Return
00DBA3  1                                               ; $DBA1: F0 0C
00DBA3  1               
00DBA3  1               ; ----------------------------------------------------------------------------
00DBA3  1               ; Use the calculated object offset to inspect its state at $056D,X.
00DBA3  1               ; ----------------------------------------------------------------------------
00DBA3  1               
00DBA3  1  AA               tax                         ; $DBA3: AA
00DBA4  1               
00DBA4  1  BD 6D 05         lda $056D,x                 ; $DBA4: BD 6D 05
00DBA7  1  F0 05            beq TestCurrentObjectRegion_Shift
00DBA9  1                                               ; $DBA7: F0 05
00DBA9  1               
00DBA9  1               ; ----------------------------------------------------------------------------
00DBA9  1               ; For an active object, combine the selector comparison with carry.
00DBA9  1               ;
00DBA9  1               ; CPY #$06 establishes carry, ROL moves it into A, and ADC #$00 incorporates
00DBA9  1               ; the resulting carry state.
00DBA9  1               ; ----------------------------------------------------------------------------
00DBA9  1               
00DBA9  1  C0 06            cpy #$06                    ; $DBA9: C0 06
00DBAB  1  2A               rol                         ; $DBAB: 2A
00DBAC  1  69 00            adc #$00                    ; $DBAC: 69 00
00DBAE  1               
00DBAE  1               ; ----------------------------------------------------------------------------
00DBAE  1               ; Return bit zero of A in carry.
00DBAE  1               ; ----------------------------------------------------------------------------
00DBAE  1               
00DBAE  1               TestCurrentObjectRegion_Shift:  ; $DBAE
00DBAE  1  4A               lsr                         ; $DBAE: 4A
00DBAF  1               
00DBAF  1               TestCurrentObjectRegion_Return: ; $DBAF
00DBAF  1  60               rts                         ; $DBAF: 60
00DBB0  1               
00DBB0  1               ; ============================================================================
00DBB0  1               ; $DBB0-$DBB7
00DBB0  1               ; Selector-specific input-mask table.
00DBB0  1               ;
00DBB0  1               ; Used by TestCurrentObjectInput:
00DBB0  1               ;
00DBB0  1               ;     jsr GetCurrentObjectSelectorAndState
00DBB0  1               ;     lda InputState1
00DBB0  1               ;     and InputMaskTable,y
00DBB0  1               ;
00DBB0  1               ; Y selects one of eight masks. Entries occur in identical pairs, suggesting
00DBB0  1               ; that adjacent selector values share the same accepted input bits.
00DBB0  1               ; ============================================================================
00DBB0  1               
00DBB0  1               InputMaskTable:                 ; $DBB0
00DBB0  1  00 00            .byte $00,$00               ; Selectors $00-$01: no accepted input
00DBB2  1  05 05            .byte $05,$05               ; Selectors $02-$03: bits $01 and $04
00DBB4  1  0C 0C            .byte $0C,$0C               ; Selectors $04-$05: bits $04 and $08
00DBB6  1  06 06            .byte $06,$06               ; Selectors $06-$07: bits $02 and $04
00DBB8  1               
00DBB8  1               ; ============================================================================
00DBB8  1               ; $DBB8-$DBF5
00DBB8  1               ; Update the current object's animation frame and return a six-tick delay.
00DBB8  1               ;
00DBB8  1               ; The routine derives one of eight animation ranges from the object's state at
00DBB8  1               ; $056D/$056E and an additional condition returned by $E6B7. When permitted,
00DBB8  1               ; it advances $039A,X and wraps or clamps the frame through two lookup tables.
00DBB8  1               ;
00DBB8  1               ; Return:
00DBB8  1               ;   A = $06
00DBB8  1               ;
00DBB8  1               ; Carry from $E6B7 can skip the animation update entirely.
00DBB8  1               ; ============================================================================
00DBB8  1               
00DBB8  1               ; ----------------------------------------------------------------------------
00DBB8  1               ; Contract:
00DBB8  1               ;   Description: Implements Select Secondary Object Delay.
00DBB8  1               ;   Entry: Registers: A, X; Memory: pendingaudioflags, currentobjectindex, $056e, $056d, $039a
00DBB8  1               ;   Returns/products: Registers/clobbers: A, X, Y
00DBB8  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00DBB8  1               ;   Memory effects: pendingaudioflags, $039a
00DBB8  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00DBB8  1               ;          comparison, load, or store path and are not a stable API product.
00DBB8  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 7.
00DBB8  1               ; ----------------------------------------------------------------------------
00DBB8  1               SelectSecondaryObjectDelay:     ; $DBB8
00DBB8  1  A5 FE            lda PendingAudioFlags             ; $DBB8: A5 FE
00DBBA  1  09 04            ora #$04                    ; $DBBA: 09 04
00DBBC  1  85 FE            sta PendingAudioFlags             ; $DBBC: 85 FE
00DBBE  1               
00DBBE  1               ; ----------------------------------------------------------------------------
00DBBE  1               ; Update or test the current object.
00DBBE  1               ;
00DBBE  1               ; Carry set skips directly to the fixed delay return.
00DBBE  1               ; ----------------------------------------------------------------------------
00DBBE  1               
00DBBE  1  A6 E1            ldx CurrentObjectIndex      ; $DBBE: A6 E1
00DBC0  1  20 B7 E6         jsr ClearMovementTransforms                   ; $DBC0: 20 B7 E6
00DBC3  1  B0 2E            bcs SecondaryObjectDelay_Return
00DBC5  1                                               ; $DBC3: B0 2E
00DBC5  1               
00DBC5  1               ; ----------------------------------------------------------------------------
00DBC5  1               ; Derive a compact animation-range selector from $056D,X and $056E,X.
00DBC5  1               ;
00DBC5  1               ; Bit flow:
00DBC5  1               ;
00DBC5  1               ;   1. ASL $056E,X places its high bit in carry.
00DBC5  1               ;   2. ROL A shifts that carry into $056D,X.
00DBC5  1               ;   3. A second ROL expands the selector before it is saved.
00DBC5  1               ; ----------------------------------------------------------------------------
00DBC5  1               
00DBC5  1  A6 E1            ldx CurrentObjectIndex      ; $DBC5: A6 E1
00DBC7  1               
00DBC7  1  BD 6E 05         lda $056E,x                 ; $DBC7: BD 6E 05
00DBCA  1  0A               asl                         ; $DBCA: 0A
00DBCB  1               
00DBCB  1  BD 6D 05         lda $056D,x                 ; $DBCB: BD 6D 05
00DBCE  1  2A               rol                         ; $DBCE: 2A
00DBCF  1  2A               rol                         ; $DBCF: 2A
00DBD0  1               
00DBD0  1  48               pha                         ; $DBD0: 48
00DBD1  1                                               ; Preserve the preliminary selector.
00DBD1  1               
00DBD1  1               ; ----------------------------------------------------------------------------
00DBD1  1               ; Run the object helper again.
00DBD1  1               ;
00DBD1  1               ; The helper may update X and returns a condition in carry.
00DBD1  1               ; ----------------------------------------------------------------------------
00DBD1  1               
00DBD1  1  20 B7 E6         jsr ClearMovementTransforms                   ; $DBD1: 20 B7 E6
00DBD4  1               
00DBD4  1  68               pla                         ; $DBD4: 68
00DBD5  1  B0 1C            bcs SecondaryObjectDelay_Return
00DBD7  1                                               ; $DBD5: B0 1C
00DBD7  1               
00DBD7  1               ; ----------------------------------------------------------------------------
00DBD7  1               ; Incorporate whether X is at least $15 into the selector.
00DBD7  1               ;
00DBD7  1               ; CPX #$15 sets carry, and ROL shifts that condition into A.
00DBD7  1               ; ----------------------------------------------------------------------------
00DBD7  1               
00DBD7  1  E0 15            cpx #$15                    ; $DBD7: E0 15
00DBD9  1  2A               rol                         ; $DBD9: 2A
00DBDA  1               
00DBDA  1  29 07            and #$07                    ; $DBDA: 29 07
00DBDC  1  A8               tay                         ; $DBDC: A8
00DBDD  1                                               ; Y selects one of eight animation ranges.
00DBDD  1               
00DBDD  1               ; ----------------------------------------------------------------------------
00DBDD  1               ; Load the current frame and increment it.
00DBDD  1               ;
00DBDD  1               ; The original frame remains in A for the threshold comparisons.
00DBDD  1               ; ----------------------------------------------------------------------------
00DBDD  1               
00DBDD  1  BD 9A 03         lda $039A,x                 ; $DBDD: BD 9A 03
00DBE0  1  FE 9A 03         inc $039A,x                 ; $DBE0: FE 9A 03
00DBE3  1               
00DBE3  1               ; ----------------------------------------------------------------------------
00DBE3  1               ; Compare the original frame against the upper and lower bounds.
00DBE3  1               ;
00DBE3  1               ; The table bases intentionally overlap:
00DBE3  1               ;
00DBE3  1               ;   SecondaryAnimationBaseTable,Y
00DBE3  1               ;   SecondaryAnimationLimitTable,Y
00DBE3  1               ;
00DBE3  1               ; If the frame lies outside the permitted range, reset it to the base frame.
00DBE3  1               ; ----------------------------------------------------------------------------
00DBE3  1               
00DBE3  1  D9 FE DB         cmp SecondaryAnimationLimitTable,y
00DBE6  1                                               ; $DBE3: D9 FE DB
00DBE6  1  B0 05            bcs SecondaryObjectDelay_ResetFrame
00DBE8  1                                               ; $DBE6: B0 05
00DBE8  1               
00DBE8  1  D9 F6 DB         cmp SecondaryAnimationBaseTable,y
00DBEB  1                                               ; $DBE8: D9 F6 DB
00DBEB  1  B0 06            bcs SecondaryObjectDelay_Return
00DBED  1                                               ; $DBEB: B0 06
00DBED  1               
00DBED  1               SecondaryObjectDelay_ResetFrame: ; $DBED
00DBED  1  B9 F6 DB         lda SecondaryAnimationBaseTable,y
00DBF0  1                                               ; $DBED: B9 F6 DB
00DBF0  1  9D 9A 03         sta $039A,x                 ; $DBF0: 9D 9A 03
00DBF3  1               
00DBF3  1               ; ----------------------------------------------------------------------------
00DBF3  1               ; Return a fixed six-tick delay.
00DBF3  1               ; ----------------------------------------------------------------------------
00DBF3  1               
00DBF3  1               SecondaryObjectDelay_Return:    ; $DBF3
00DBF3  1  A9 06            lda #$06                    ; $DBF3: A9 06
00DBF5  1  60               rts                         ; $DBF5: 60
00DBF6  1               
00DBF6  1               ; ============================================================================
00DBF6  1               ; $DBF6-$DC05
00DBF6  1               ; Parallel secondary-object animation tables.
00DBF6  1               ;
00DBF6  1               ; SelectSecondaryObjectDelay uses the same Y index with both tables:
00DBF6  1               ;
00DBF6  1               ;   SecondaryAnimationBaseTable,Y
00DBF6  1               ;       Base or reset animation frame.
00DBF6  1               ;
00DBF6  1               ;   SecondaryAnimationLimitTable,Y
00DBF6  1               ;       Upper animation-frame limit.
00DBF6  1               ;
00DBF6  1               ; The animation helper increments the current frame, then resets it to the
00DBF6  1               ; corresponding base frame whenever it falls below the base or reaches the
00DBF6  1               ; upper limit.
00DBF6  1               ; ============================================================================
00DBF6  1               
00DBF6  1               ; ----------------------------------------------------------------------------
00DBF6  1               ; Base/reset animation frames.
00DBF6  1               ; ----------------------------------------------------------------------------
00DBF6  1               
00DBF6  1               SecondaryAnimationBaseTable:    ; $DBF6
00DBF6  1  4D 1A 50 1E      .byte $4D,$1A,$50,$1E
00DBFA  1  56 27 53 23      .byte $56,$27,$53,$23
00DBFE  1               
00DBFE  1               ; ----------------------------------------------------------------------------
00DBFE  1               ; Upper animation-frame limits.
00DBFE  1               ; ----------------------------------------------------------------------------
00DBFE  1               
00DBFE  1               SecondaryAnimationLimitTable:   ; $DBFE
00DBFE  1  4F 1C 52 20      .byte $4F,$1C,$52,$20
00DC02  1  58 29 55 25      .byte $58,$29,$55,$25
00DC06  1               
00DC06  1               
00DC06  1               ; ============================================================================
00DC06  1               ; $DC06-$DC28
00DC06  1               ; Test the current object's adjusted X and Y coordinate regions.
00DC06  1               ;
00DC06  1               ; Entry:
00DC06  1               ;   X = ignored. The routine reloads X from CurrentObjectIndex.
00DC06  1               ;   Y = coordinate-adjustment table index.
00DC06  1               ;
00DC06  1               ; Return:
00DC06  1               ;   A contains the final comparison value.
00DC06  1               ;
00DC06  1               ;   Carry set:
00DC06  1               ;       The adjusted X coordinate is at least two, or the adjusted Y
00DC06  1               ;       coordinate is at least two.
00DC06  1               ;
00DC06  1               ;   Carry clear:
00DC06  1               ;       Both adjusted coordinate values are below two.
00DC06  1               ;
00DC06  1               ; The low coordinate bytes are shifted only to place bit 7 into carry. That
00DC06  1               ; carry is then added to the corresponding high coordinate byte.
00DC06  1               ; ============================================================================
00DC06  1               
00DC06  1               TestCurrentObjectCoordinateRegion: ; $DC06
00DC06  1  A6 E1            ldx CurrentObjectIndex      ; $DC06: A6 E1
00DC08  1               
00DC08  1               ; ----------------------------------------------------------------------------
00DC08  1               ; Test the adjusted horizontal coordinate.
00DC08  1               ;
00DC08  1               ; The horizontal high byte is adjusted using the table based at $DC2A,Y:
00DC08  1               ;
00DC08  1               ;   adjustedX = $050A,X + Table_DC2A,Y + carry($0509,X << 1) + 1
00DC08  1               ; ----------------------------------------------------------------------------
00DC08  1               
00DC08  1  BD 09 05         lda $0509,x                 ; $DC08: BD 09 05
00DC0B  1  0A               asl                         ; $DC0B: 0A
00DC0C  1                                               ; Carry = bit 7 of the horizontal low byte.
00DC0C  1               
00DC0C  1  BD 0A 05         lda $050A,x                 ; $DC0C: BD 0A 05
00DC0F  1  79 2A DC         adc HorizontalAdjustmentTable,y
00DC12  1                                               ; $DC0F: 79 2A DC
00DC12  1               
00DC12  1  18               clc                         ; $DC12: 18
00DC13  1  69 01            adc #$01                    ; $DC13: 69 01
00DC15  1               
00DC15  1  C9 02            cmp #$02                    ; $DC15: C9 02
00DC17  1  B0 0F            bcs TestCurrentObjectCoordinateRegion_Return
00DC19  1                                               ; $DC17: B0 0F
00DC19  1               
00DC19  1               ; ----------------------------------------------------------------------------
00DC19  1               ; The adjusted horizontal coordinate is below two.
00DC19  1               ; Test the adjusted vertical coordinate.
00DC19  1               ;
00DC19  1               ; The vertical high byte is adjusted using the table based at $DC29,Y:
00DC19  1               ;
00DC19  1               ;   adjustedY = $053B,X + Table_DC29,Y + carry($053A,X << 1) + 1
00DC19  1               ; ----------------------------------------------------------------------------
00DC19  1               
00DC19  1  BD 3A 05         lda $053A,x                 ; $DC19: BD 3A 05
00DC1C  1  0A               asl                         ; $DC1C: 0A
00DC1D  1                                               ; Carry = bit 7 of the vertical low byte.
00DC1D  1               
00DC1D  1  BD 3B 05         lda $053B,x                 ; $DC1D: BD 3B 05
00DC20  1  79 29 DC         adc VerticalAdjustmentTable,y
00DC23  1                                               ; $DC20: 79 29 DC
00DC23  1               
00DC23  1  18               clc                         ; $DC23: 18
00DC24  1  69 01            adc #$01                    ; $DC24: 69 01
00DC26  1               
00DC26  1  C9 02            cmp #$02                    ; $DC26: C9 02
00DC28  1               
00DC28  1               TestCurrentObjectCoordinateRegion_Return: ; $DC28
00DC28  1  60               rts                         ; $DC28: 60
00DC29  1               
00DC29  1               ; ============================================================================
00DC29  1               ; $DC29-$DC30
00DC29  1               ; Overlapping signed coordinate-adjustment tables.
00DC29  1               ;
00DC29  1               ; The routine accesses:
00DC29  1               ;
00DC29  1               ;   VerticalAdjustmentTable,Y   at $DC29
00DC29  1               ;   HorizontalAdjustmentTable,Y at $DC2A
00DC29  1               ;
00DC29  1               ; The table index in Y is supplied by the caller.
00DC29  1               ; ============================================================================
00DC29  1               
00DC29  1               VerticalAdjustmentTable:        ; $DC29
00DC29  1  08               .byte $08
00DC2A  1               
00DC2A  1               HorizontalAdjustmentTable:      ; $DC2A
00DC2A  1  00 F8 00 08      .byte $00,$F8,$00,$08
00DC2E  1  00 F8 00         .byte $00,$F8,$00
00DC31  1               
00DC31  1               ; ============================================================================
00DC31  1               ; $DC31-$DC87
00DC31  1               ; Initialize object-processing parameters, process a list of event slots,
00DC31  1               ; dispatch one command for each listed object, and leave through the common
00DC31  1               ; engine exit.
00DC31  1               ; ============================================================================
00DC31  1               
00DC31  1               InitializeObjectEventSequence:  ; $DC31
00DC31  1  A9 20            lda #$20                    ; $DC31: A9 20
00DC33  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $DC33: 20 41 EB
00DC36  1               
00DC36  1               ; ----------------------------------------------------------------------------
00DC36  1               ; Clear working object indices.
00DC36  1               ; ----------------------------------------------------------------------------
00DC36  1               
00DC36  1  A9 00            lda #$00                    ; $DC36: A9 00
00DC38  1  85 A4            sta $A4                     ; $DC38: 85 A4
00DC3A  1  85 A9            sta $A9                     ; $DC3A: 85 A9
00DC3C  1               
00DC3C  1               ; ----------------------------------------------------------------------------
00DC3C  1               ; Initialize object-selection bounds.
00DC3C  1               ; ----------------------------------------------------------------------------
00DC3C  1               
00DC3C  1  A9 04            lda #$04                    ; $DC3C: A9 04
00DC3E  1  85 A8            sta $A8                     ; $DC3E: 85 A8
00DC40  1               
00DC40  1  A9 16            lda #$16                    ; $DC40: A9 16
00DC42  1  85 A7            sta $A7                     ; $DC42: 85 A7
00DC44  1               
00DC44  1               ; ----------------------------------------------------------------------------
00DC44  1               ; Select initial values for $A6 and $A5.
00DC44  1               ;
00DC44  1               ; Defaults:
00DC44  1               ;   Y = $14
00DC44  1               ;   X = $10
00DC44  1               ;
00DC44  1               ; If RandomVerticalMotion is negative:
00DC44  1               ;   Y = $12
00DC44  1               ;
00DC44  1               ; Otherwise, when RandomVerticalMotion is at least $1E and ObjectSelectionLowerBound is zero:
00DC44  1               ;   X = $0E
00DC44  1               ; ----------------------------------------------------------------------------
00DC44  1               
00DC44  1  A0 14            ldy #$14                    ; $DC44: A0 14
00DC46  1  A2 10            ldx #$10                    ; $DC46: A2 10
00DC48  1               
00DC48  1  A5 90            lda RandomVerticalMotion          ; $DC48: A5 90
00DC4A  1  10 04            bpl InitializeObjectEventSequence_CheckUpper
00DC4C  1                                               ; $DC4A: 10 04
00DC4C  1               
00DC4C  1  A0 12            ldy #$12                    ; $DC4C: A0 12
00DC4E  1  D0 0A            bne InitializeObjectEventSequence_SaveBounds
00DC50  1                                               ; $DC4E: D0 0A
00DC50  1                                               ; Always taken because Y is nonzero.
00DC50  1               
00DC50  1               InitializeObjectEventSequence_CheckUpper: ; $DC50
00DC50  1  C9 1E            cmp #$1E                    ; $DC50: C9 1E
00DC52  1  30 06            bmi InitializeObjectEventSequence_SaveBounds
00DC54  1                                               ; $DC52: 30 06
00DC54  1               
00DC54  1  A5 A5            lda ObjectSelectionLowerBound         ; $DC54: A5 A5
00DC56  1  D0 02            bne InitializeObjectEventSequence_SaveBounds
00DC58  1                                               ; $DC56: D0 02
00DC58  1               
00DC58  1  A2 0E            ldx #$0E                    ; $DC58: A2 0E
00DC5A  1               
00DC5A  1               InitializeObjectEventSequence_SaveBounds: ; $DC5A
00DC5A  1  84 A6            sty $A6                     ; $DC5A: 84 A6
00DC5C  1  86 A5            stx ObjectSelectionLowerBound         ; $DC5C: 86 A5
00DC5E  1               
00DC5E  1               ; ----------------------------------------------------------------------------
00DC5E  1               ; Process event slots selected by the nine-byte table at $DC88.
00DC5E  1               ;
00DC5E  1               ; X begins at eight and counts down through zero. The table value is loaded
00DC5E  1               ; into Y and passed to $EB66.
00DC5E  1               ; ----------------------------------------------------------------------------
00DC5E  1               
00DC5E  1  A2 08            ldx #$08                    ; $DC5E: A2 08
00DC60  1               
00DC60  1               InitializeObjectEventSequence_ProcessEvents: ; $DC60
00DC60  1  86 B8            stx $B8                     ; $DC60: 86 B8
00DC62  1               
00DC62  1  BC 88 DC         ldy ObjectEventSlotTable,x  ; $DC62: BC 88 DC
00DC65  1  20 66 EB         jsr DispatchNextQueuedEvent                   ; $DC65: 20 66 EB
00DC68  1               
00DC68  1  20 48 EB         jsr SelectObjectEventBank1                   ; $DC68: 20 48 EB
00DC6B  1               
00DC6B  1  A6 B8            ldx $B8                     ; $DC6B: A6 B8
00DC6D  1  CA               dex                         ; $DC6D: CA
00DC6E  1  10 F0            bpl InitializeObjectEventSequence_ProcessEvents
00DC70  1                                               ; $DC6E: 10 F0
00DC70  1               
00DC70  1               ; ----------------------------------------------------------------------------
00DC70  1               ; Dispatch a command for each object/event-table entry in reverse order.
00DC70  1               ; ----------------------------------------------------------------------------
00DC70  1               
00DC70  1  A0 08            ldy #$08                    ; $DC70: A0 08
00DC72  1               
00DC72  1               InitializeObjectEventSequence_DispatchLoop: ; $DC72
00DC72  1  84 B8            sty $B8                     ; $DC72: 84 B8
00DC74  1               
00DC74  1  BE 88 DC         ldx ObjectEventSlotTable,y  ; $DC74: BE 88 DC
00DC77  1  20 9B E2         jsr DispatchInlineObjectCommand                   ; $DC77: 20 9B E2
00DC7A  1               
00DC7A  1                   ; Inline record consumed by $E29B.
00DC7A  1                   ;
00DC7A  1                   ; The stored address is $DD47, apparently the continuation/handler used
00DC7A  1                   ; for each selected object. Its exact dispatch convention will be confirmed
00DC7A  1                   ; when $E29B is decoded.
00DC7A  1  00 47 DD         .byte $00,$47,$DD           ; $DC7A-$DC7C
00DC7D  1               
00DC7D  1  20 48 EB         jsr SelectObjectEventBank1                   ; $DC7D: 20 48 EB
00DC80  1               
00DC80  1  A4 B8            ldy $B8                     ; $DC80: A4 B8
00DC82  1  88               dey                         ; $DC82: 88
00DC83  1  10 ED            bpl InitializeObjectEventSequence_DispatchLoop
00DC85  1                                               ; $DC83: 10 ED
00DC85  1               
00DC85  1               ; ----------------------------------------------------------------------------
00DC85  1               ; Leave through the common engine exit.
00DC85  1               ; ----------------------------------------------------------------------------
00DC85  1               
00DC85  1  4C 6A EB         jmp CommonEngineExit                   ; $DC85: 4C 6A EB
00DC88  1               
00DC88  1               ; ============================================================================
00DC88  1               ; $DC88-$DC90
00DC88  1               ; Object/event-slot lookup table.
00DC88  1               ;
00DC88  1               ; InitializeObjectEventSequence uses this table twice:
00DC88  1               ;
00DC88  1               ;   1. Each value is passed to $EB66 as an event-slot index.
00DC88  1               ;   2. Each value is loaded into X before dispatching the inline record
00DC88  1               ;      through $E29B.
00DC88  1               ;
00DC88  1               ; The values are also valid even-numbered object-array offsets. Dividing each
00DC88  1               ; value by two gives the associated compact object-state index.
00DC88  1               ; ============================================================================
00DC88  1               
00DC88  1               ObjectEventSlotTable:           ; $DC88
00DC88  1  04               .byte $04                   ; Object/event offset $04, compact index $02
00DC89  1  0E               .byte $0E                   ; Object/event offset $0E, compact index $07
00DC8A  1  10               .byte $10                   ; Object/event offset $10, compact index $08
00DC8B  1  12               .byte $12                   ; Object/event offset $12, compact index $09
00DC8C  1  14               .byte $14                   ; Object/event offset $14, compact index $0A
00DC8D  1  16               .byte $16                   ; Object/event offset $16, compact index $0B
00DC8E  1  1E               .byte $1E                   ; Object/event offset $1E, compact index $0F
00DC8F  1  20               .byte $20                   ; Object/event offset $20, compact index $10
00DC90  1  22               .byte $22                   ; Object/event offset $22, compact index $11
00DC91  1               
00DC91  1               ; ============================================================================
00DC91  1               ; $DC91-$DCA0
00DC91  1               ; Wait until the current object's geometry or region test clears.
00DC91  1               ;
00DC91  1               ; The routine repeatedly:
00DC91  1               ;
00DC91  1               ;   1. Calls the setup helper at $E2DE.
00DC91  1               ;   2. Waits using the delay returned in A.
00DC91  1               ;   3. Prepares geometry arguments through $E4B8.
00DC91  1               ;   4. Tests the resulting region through $E55F.
00DC91  1               ;
00DC91  1               ; A carry-set result restarts the routine. Carry clear leaves through the
00DC91  1               ; common engine exit.
00DC91  1               ; ============================================================================
00DC91  1               
00DC91  1               WaitForObjectRegionClear:       ; $DC91
00DC91  1  20 DE E2         jsr UpdateCurrentObjectAnimationDelay                   ; $DC91: 20 DE E2
00DC94  1                                               ; Returns a delay value in A.
00DC94  1               
00DC94  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $DC94: 20 41 EB
00DC97  1                                               ; Wait for the delay supplied in A.
00DC97  1               
00DC97  1               WaitForObjectRegionClear_Test:
00DC97  1  20 B8 E4         jsr SelectGeometryRecordFromObject                   ; $DC97: 20 B8 E4
00DC9A  1                                               ; Prepare the geometry/region arguments.
00DC9A  1               
00DC9A  1  20 5F E5         jsr ApplyCurrentObjectGeometry                   ; $DC9A: 20 5F E5
00DC9D  1                                               ; Test the prepared region.
00DC9D  1               
00DC9D  1  B0 F2            bcs WaitForObjectRegionClear
00DC9F  1                                               ; $DC9D: B0 F2
00DC9F  1               
00DC9F  1  4C 6A EB         jmp CommonEngineExit                   ; $DC9F: 4C 6A EB
00DCA2  1               
00DCA2  1               ; ============================================================================
00DCA2  1               ; $DCA2-$DCB9
00DCA2  1               ; Dispatch an inline command for six entries from ObjectEventSlotTable.
00DCA2  1               ;
00DCA2  1               ; The routine processes table indices five through zero:
00DCA2  1               ;
00DCA2  1               ;   Y=$05 -> object/event offset $16
00DCA2  1               ;   Y=$04 -> object/event offset $14
00DCA2  1               ;   Y=$03 -> object/event offset $12
00DCA2  1               ;   Y=$02 -> object/event offset $10
00DCA2  1               ;   Y=$01 -> object/event offset $0E
00DCA2  1               ;   Y=$00 -> object/event offset $04
00DCA2  1               ;
00DCA2  1               ; For each entry:
00DCA2  1               ;   1. Save the table index in $B8.
00DCA2  1               ;   2. Load the object/event offset into X.
00DCA2  1               ;   3. Dispatch the inline record through $E29B.
00DCA2  1               ;   4. Wait for the next frame.
00DCA2  1               ; ============================================================================
00DCA2  1               
00DCA2  1               DispatchSixObjectEvents:        ; $DCA2
00DCA2  1  A0 05            ldy #$05                    ; $DCA2: A0 05
00DCA4  1               
00DCA4  1               DispatchSixObjectEvents_Loop:   ; $DCA4
00DCA4  1  84 B8            sty $B8                     ; $DCA4: 84 B8
00DCA6  1               
00DCA6  1  BE 88 DC         ldx ObjectEventSlotTable,y  ; $DCA6: BE 88 DC
00DCA9  1               
00DCA9  1  20 9B E2         jsr DispatchInlineObjectCommand                   ; $DCA9: 20 9B E2
00DCAC  1               
00DCAC  1                   ; Inline record consumed by $E29B.
00DCAC  1                   ;
00DCAC  1                   ; The record contains a leading zero byte followed by address $DC96.
00DCAC  1                   ; The address points inside WaitForObjectRegionClear:
00DCAC  1                   ;
00DCAC  1                   ;   $DC94: JSR $EB41
00DCAC  1                   ;   $DC97: JSR $E4B8
00DCAC  1                   ;
00DCAC  1                   ; A stored address of $DC96 is one byte before the entry at $DC97,
00DCAC  1                   ; suggesting an RTS-style dispatch to $DC97.
00DCAC  1  00               .byte $00                   ; $DCAC
00DCAD  1  96 DC            .word WaitForObjectRegionClear_Test - 1
00DCAF  1                                               ; $DCAD-$DCAE: $DC96
00DCAF  1               
00DCAF  1  20 48 EB         jsr SelectObjectEventBank1                   ; $DCAF: 20 48 EB
00DCB2  1               
00DCB2  1  A4 B8            ldy $B8                     ; $DCB2: A4 B8
00DCB4  1  88               dey                         ; $DCB4: 88
00DCB5  1               
00DCB5  1  D0 ED            bne DispatchSixObjectEvents_Loop
00DCB7  1                                               ; $DCB5: D0 ED
00DCB7  1               
00DCB7  1               ; ----------------------------------------------------------------------------
00DCB7  1               ; Leave through the common engine exit.
00DCB7  1               ;
00DCB7  1               ; Because the loop uses BNE rather than BPL, processing stops after Y is
00DCB7  1               ; decremented from one to zero. The table entry at index zero is therefore not
00DCB7  1               ; dispatched by this loop. The actual processed indices are five through one.
00DCB7  1               ; ----------------------------------------------------------------------------
00DCB7  1               
00DCB7  1  4C 6A EB         jmp CommonEngineExit                   ; $DCB7: 4C 6A EB
00DCBA  1               
00DCBA  1               ; ============================================================================
00DCBA  1               ; $DCBA-$DCDF
00DCBA  1               ; Select and initialize an active object or event slot.
00DCBA  1               ;
00DCBA  1               ; The routine does nothing if $A4 already contains a nonzero object offset.
00DCBA  1               ; Otherwise, it checks the base object state and searches for a usable
00DCBA  1               ; selector. On success, it stores the selected offset in $A4 and clears the
00DCBA  1               ; corresponding zero-page state byte at $A4,X.
00DCBA  1               ; ============================================================================
00DCBA  1               
00DCBA  1               ; ----------------------------------------------------------------------------
00DCBA  1               ; Contract:
00DCBA  1               ;   Description: Implements Select Active Object.
00DCBA  1               ;   Entry: Registers: A, X; Memory: $a4, $056c
00DCBA  1               ;   Returns/products: Registers/clobbers: A, X
00DCBA  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00DCBA  1               ;   Memory effects: $a4
00DCBA  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00DCBA  1               ;          comparison, load, or store path and are not a stable API product.
00DCBA  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00DCBA  1               ; ----------------------------------------------------------------------------
00DCBA  1               SelectActiveObject:             ; $DCBA
00DCBA  1  A5 A4            lda $A4                     ; $DCBA: A5 A4
00DCBC  1  D0 21            bne SelectActiveObject_Return
00DCBE  1                                               ; $DCBC: D0 21
00DCBE  1               
00DCBE  1               ; ----------------------------------------------------------------------------
00DCBE  1               ; When the base object's high state at $056C is negative after comparison with
00DCBE  1               ; three, use the alternate selector helper at $DF45.
00DCBE  1               ; ----------------------------------------------------------------------------
00DCBE  1               
00DCBE  1  AD 6C 05         lda $056C                   ; $DCBE: AD 6C 05
00DCC1  1  C9 03            cmp #$03                    ; $DCC1: C9 03
00DCC3  1  30 13            bmi SelectActiveObject_Alternate
00DCC5  1                                               ; $DCC3: 30 13
00DCC5  1               
00DCC5  1               ; ----------------------------------------------------------------------------
00DCC5  1               ; Obtain a candidate selector through $DF08.
00DCC5  1               ;
00DCC5  1               ; Values seven or greater are rejected.
00DCC5  1               ; ----------------------------------------------------------------------------
00DCC5  1               
00DCC5  1  20 08 DF         jsr TestCurrentObjectGeometry                   ; $DCC5: 20 08 DF
00DCC8  1               
00DCC8  1  C9 07            cmp #$07                    ; $DCC8: C9 07
00DCCA  1  B0 13            bcs SelectActiveObject_Return
00DCCC  1                                               ; $DCCA: B0 13
00DCCC  1               
00DCCC  1               ; ----------------------------------------------------------------------------
00DCCC  1               ; Convert the candidate selector into an object offset.
00DCCC  1               ;
00DCCC  1               ; GetCurrentObjectSelectorAndState returns:
00DCCC  1               ;   X = selected object offset
00DCCC  1               ;   Y = related selector value
00DCCC  1               ; ----------------------------------------------------------------------------
00DCCC  1               
00DCCC  1               SelectActiveObject_Save:        ; $DCCC
00DCCC  1  20 DC E3         jsr GetCurrentObjectSelectorAndState                   ; $DCCC: 20 DC E3
00DCCF  1               
00DCCF  1  86 A4            stx $A4                     ; $DCCF: 86 A4
00DCD1  1               
00DCD1  1               ; ----------------------------------------------------------------------------
00DCD1  1               ; Clear the selected zero-page object-state entry.
00DCD1  1               ;
00DCD1  1               ; X is explicitly changed to zero, so STX $A4,X stores zero at address $A4.
00DCD1  1               ; This is distinct from clearing the variable at zero-page address $A4.
00DCD1  1               ; ----------------------------------------------------------------------------
00DCD1  1               
00DCD1  1  A2 00            ldx #$00                    ; $DCD1: A2 00
00DCD3  1  96 A4            stx $A4,y                   ; $DCD3: 96 A4
00DCD5  1               
00DCD5  1  4C 48 DD         jmp ContinueObjectProcessing; $DCD5: 4C 48 DD
00DCD8  1               
00DCD8  1               ; ----------------------------------------------------------------------------
00DCD8  1               ; Alternate selection path.
00DCD8  1               ;
00DCD8  1               ; Continue requesting a selector until the returned value is at least eight.
00DCD8  1               ; The successful value remains in A while GetCurrentObjectSelectorAndState derives the selected object.
00DCD8  1               ; ----------------------------------------------------------------------------
00DCD8  1               
00DCD8  1               SelectActiveObject_Alternate:   ; $DCD8
00DCD8  1  20 45 DF         jsr CalculateCurrentObjectGeometry                   ; $DCD8: 20 45 DF
00DCDB  1               
00DCDB  1  C9 08            cmp #$08                    ; $DCDB: C9 08
00DCDD  1  90 ED            bcc SelectActiveObject_Save ; $DCDD: 90 ED
00DCDF  1               
00DCDF  1               SelectActiveObject_Return:      ; $DCDF
00DCDF  1  60               rts                         ; $DCDF: 60
00DCE0  1               
00DCE0  1               ; ============================================================================
00DCE0  1               ; $DCE0-$DD20
00DCE0  1               ; Initialize the selected object's state, run geometry tests, and select one
00DCE0  1               ; of two shared continuation paths.
00DCE0  1               ;
00DCE0  1               ; Entry:
00DCE0  1               ;   X = selected object offset
00DCE0  1               ;
00DCE0  1               ; The routine saves the incoming object offset, derives its compact state
00DCE0  1               ; index, stores the original offset into $0595,X, then executes a sequence of
00DCE0  1               ; object and geometry helpers.
00DCE0  1               ; ============================================================================
00DCE0  1               
00DCE0  1               ProcessSelectedObject:          ; $DCE0
00DCE0  1  8A               txa                         ; $DCE0: 8A
00DCE1  1  A8               tay                         ; $DCE1: A8
00DCE2  1                                               ; Preserve the incoming object offset in Y.
00DCE2  1               
00DCE2  1  20 68 DA         jsr GetCurrentObjectStateIndex
00DCE5  1                                               ; $DCE2: 20 68 DA
00DCE5  1                                               ; X = CurrentObjectIndex >> 1.
00DCE5  1               
00DCE5  1  98               tya                         ; $DCE5: 98
00DCE6  1  9D 95 05         sta $0595,x                 ; $DCE6: 9D 95 05
00DCE9  1                                               ; Save the selected object offset.
00DCE9  1               
00DCE9  1               ; ----------------------------------------------------------------------------
00DCE9  1               ; Re-enter the object-selector routine.
00DCE9  1               ;
00DCE9  1               ; Because $A4 is now nonzero, SelectActiveObject returns immediately.
00DCE9  1               ; ----------------------------------------------------------------------------
00DCE9  1               
00DCE9  1  20 BA DC         jsr SelectActiveObject      ; $DCE9: 20 BA DC
00DCEC  1               
00DCEC  1               ; ----------------------------------------------------------------------------
00DCEC  1               ; Prepare and evaluate the selected object's geometry.
00DCEC  1               ; ----------------------------------------------------------------------------
00DCEC  1               ProcessSelectedObject_Geometry:
00DCEC  1  20 74 E4         jsr SelectGeometryRecord_Default                   ; $DCEC: 20 74 E4
00DCEF  1  20 C2 E4         jsr LoadGeometryRecord                   ; $DCEF: 20 C2 E4
00DCF2  1  20 DB E4         jsr CalculateCurrentGeometryDifference                   ; $DCF2: 20 DB E4
00DCF5  1  20 02 E5         jsr EvaluateGeometryDifference                   ; $DCF5: 20 02 E5
00DCF8  1               
00DCF8  1  C9 08            cmp #$08                    ; $DCF8: C9 08
00DCFA  1  B0 0B            bcs ProcessSelectedObject_LargeResult
00DCFC  1                                               ; $DCFA: B0 0B
00DCFC  1               
00DCFC  1               ; ----------------------------------------------------------------------------
00DCFC  1               ; For values below eight, preserve A while obtaining the current selector.
00DCFC  1               ;
00DCFC  1               ; GetCurrentObjectSelectorAndState returns X and Y. STX $A4,Y stores X into a selector-dependent
00DCFC  1               ; zero-page state slot.
00DCFC  1               ; ----------------------------------------------------------------------------
00DCFC  1               
00DCFC  1  48               pha                         ; $DCFC: 48
00DCFD  1               
00DCFD  1  20 DC E3         jsr GetCurrentObjectSelectorAndState                   ; $DCFD: 20 DC E3
00DD00  1               
00DD00  1  96 A4            stx $A4,y                   ; $DD00: 96 A4
00DD02  1               
00DD02  1  68               pla                         ; $DD02: 68
00DD03  1               
00DD03  1  C9 03            cmp #$03                    ; $DD03: C9 03
00DD05  1  90 0E            bcc ProcessSelectedObject_SmallResult
00DD07  1                                               ; $DD05: 90 0E
00DD07  1               
00DD07  1               ; ----------------------------------------------------------------------------
00DD07  1               ; Handle values three or greater, or any original result at least eight.
00DD07  1               ; ----------------------------------------------------------------------------
00DD07  1               
00DD07  1               ProcessSelectedObject_LargeResult: ; $DD07
00DD07  1  A5 C6            lda $C6                     ; $DD07: A5 C6
00DD09  1               
00DD09  1  20 13 E5         jsr BuildGeometryVector                   ; $DD09: 20 13 E5
00DD0C  1  20 28 E5         jsr StoreCurrentObjectMovement                   ; $DD0C: 20 28 E5
00DD0F  1  20 DE E2         jsr UpdateCurrentObjectAnimationDelay                   ; $DD0F: 20 DE E2
00DD12  1               
00DD12  1  4C 4A DD         jmp ContinueObjectProcessingWithDelay
00DD15  1                                               ; $DD12: 4C 4A DD
00DD15  1               
00DD15  1               ; ----------------------------------------------------------------------------
00DD15  1               ; Handle result values zero through two.
00DD15  1               ; ----------------------------------------------------------------------------
00DD15  1               
00DD15  1               ProcessSelectedObject_SmallResult: ; $DD15
00DD15  1  20 48 E5         jsr StoreGeometryInCurrentObject                   ; $DD15: 20 48 E5
00DD18  1  20 D3 E2         jsr ClearCurrentObjectMovement                   ; $DD18: 20 D3 E2
00DD1B  1  20 D4 DF         jsr UpdateCurrentObjectDisplayState                   ; $DD1B: 20 D4 DF
00DD1E  1               
00DD1E  1  4C 48 DD         jmp ContinueObjectProcessing
00DD21  1                                               ; $DD1E: 4C 48 DD
00DD21  1               
00DD21  1               ; ============================================================================
00DD21  1               ; $DD21-$DD4C
00DD21  1               ; Find an available object-state slot or continue processing the current
00DD21  1               ; selected object.
00DD21  1               ;
00DD21  1               ; The routine searches zero-page state entries $A4-$A7 when the current object
00DD21  1               ; offset is below $18. If an empty entry is found, the current object is moved
00DD21  1               ; into that slot and processing restarts at the geometry setup path at $DCEC.
00DD21  1               ;
00DD21  1               ; Otherwise, the routine performs a short delay and continues with the shared
00DD21  1               ; object-processing path beginning at $DD4D.
00DD21  1               ; ============================================================================
00DD21  1               
00DD21  1               FindAvailableObjectSlot:        ; $DD21
00DD21  1  A6 E1            ldx CurrentObjectIndex      ; $DD21: A6 E1
00DD23  1               
00DD23  1  E0 18            cpx #$18                    ; $DD23: E0 18
00DD25  1  B0 09            bcs CheckSavedObjectOffset  ; $DD25: B0 09
00DD27  1               
00DD27  1               ; ----------------------------------------------------------------------------
00DD27  1               ; Search zero-page entries $A4-$A7 for an empty slot.
00DD27  1               ;
00DD27  1               ; X begins at four and is decremented before looping, so the tested addresses
00DD27  1               ; are:
00DD27  1               ;
00DD27  1               ;   $A8 initially through indexed addressing at X=$04
00DD27  1               ;   then $A7, $A6, and $A5 as X counts down
00DD27  1               ;
00DD27  1               ; The loop intentionally stops before repeating with X=$00.
00DD27  1               ; ----------------------------------------------------------------------------
00DD27  1               
00DD27  1  A2 04            ldx #$04                    ; $DD27: A2 04
00DD29  1               
00DD29  1               FindAvailableObjectSlot_Search: ; $DD29
00DD29  1  B5 A4            lda $A4,x                   ; $DD29: B5 A4
00DD2B  1  F0 0F            beq AssignObjectToSlot      ; $DD2B: F0 0F
00DD2D  1               
00DD2D  1  CA               dex                         ; $DD2D: CA
00DD2E  1  D0 F9            bne FindAvailableObjectSlot_Search
00DD30  1                                               ; $DD2E: D0 F9
00DD30  1               
00DD30  1               ; ----------------------------------------------------------------------------
00DD30  1               ; No empty slot was found, or the current object offset is at least $18.
00DD30  1               ;
00DD30  1               ; If the saved object offset at $A9 equals CurrentObjectIndex, branch forward
00DD30  1               ; to the special path at HandleSavedObject
00DD30  1               ; ----------------------------------------------------------------------------
00DD30  1               
00DD30  1               CheckSavedObjectOffset:         ; $DD30
00DD30  1  A5 A9            lda $A9                     ; $DD30: A5 A9
00DD32  1  C5 E1            cmp CurrentObjectIndex      ; $DD32: C5 E1
00DD34  1  F0 4C            beq ObjectSelection_CheckActive       ; $DD34: F0 4C
00DD36  1               
00DD36  1               ; ----------------------------------------------------------------------------
00DD36  1               ; Run the object helper and continue at the common delay path.
00DD36  1               ; ----------------------------------------------------------------------------
00DD36  1               
00DD36  1  20 D3 E2         jsr ClearCurrentObjectMovement                   ; $DD36: 20 D3 E2
00DD39  1               
00DD39  1  4C 48 DD         jmp ContinueObjectProcessing
00DD3C  1                                               ; $DD39: 4C 48 DD
00DD3C  1               
00DD3C  1               ; ----------------------------------------------------------------------------
00DD3C  1               ; An empty zero-page object slot was found.
00DD3C  1               ;
00DD3C  1               ; Preserve the slot index in Y, derive the compact current-object state index,
00DD3C  1               ; and store the slot index into $0595,X.
00DD3C  1               ; ----------------------------------------------------------------------------
00DD3C  1               
00DD3C  1               AssignObjectToSlot:             ; $DD3C
00DD3C  1  8A               txa                         ; $DD3C: 8A
00DD3D  1  A8               tay                         ; $DD3D: A8
00DD3E  1                                               ; Y = available zero-page slot index.
00DD3E  1               
00DD3E  1  20 68 DA         jsr GetCurrentObjectStateIndex
00DD41  1                                               ; $DD3E: 20 68 DA
00DD41  1               
00DD41  1  98               tya                         ; $DD41: 98
00DD42  1  9D 95 05         sta $0595,x                 ; $DD42: 9D 95 05
00DD45  1               
00DD45  1               ; ----------------------------------------------------------------------------
00DD45  1               ; Restart selected-object processing at the geometry setup entry.
00DD45  1               ; ----------------------------------------------------------------------------
00DD45  1               
00DD45  1  4C EC DC         jmp ProcessSelectedObject_Geometry
00DD48  1                                               ; $DD45: 4C EC DC
00DD48  1               
00DD48  1               ; ============================================================================
00DD48  1               ; $DD48-$DD4C
00DD48  1               ; Shared continuation used by several earlier object-processing paths.
00DD48  1               ;
00DD48  1               ; Entry at $DD48 loads a six-tick delay.
00DD48  1               ; Entry at ContinueObjectProcessingWithDelay uses the delay already present in A.
00DD48  1               ; ============================================================================
00DD48  1               
00DD48  1               ContinueObjectProcessing:       ; $DD48
00DD48  1  A9 06            lda #$06                    ; $DD48: A9 06
00DD4A  1               
00DD4A  1               ContinueObjectProcessingWithDelay: ; $DD4A
00DD4A  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $DD4A: 20 41 EB
00DD4D  1               
00DD4D  1               ; ============================================================================
00DD4D  1               ; $DD4D-$DD77
00DD4D  1               ; Shared object-selection and routing path.
00DD4D  1               ;
00DD4D  1               ; This path checks whether CurrentObjectIndex is already assigned to one of
00DD4D  1               ; the zero-page object slots at $A4-$A8. It then evaluates global state and
00DD4D  1               ; routes to the appropriate object-processing branch.
00DD4D  1               ; ============================================================================
00DD4D  1               
00DD4D  1               ObjectSelectionSharedPath:      ; $DD4D
00DD4D  1  A5 E1            lda CurrentObjectIndex      ; $DD4D: A5 E1
00DD4F  1               
00DD4F  1               ; ----------------------------------------------------------------------------
00DD4F  1               ; Search the five zero-page object slots $A8 through $A4.
00DD4F  1               ;
00DD4F  1               ; X begins at four:
00DD4F  1               ;
00DD4F  1               ;   X=$04 -> $A8
00DD4F  1               ;   X=$03 -> $A7
00DD4F  1               ;   X=$02 -> $A6
00DD4F  1               ;   X=$01 -> $A5
00DD4F  1               ;   X=$00 -> $A4
00DD4F  1               ;
00DD4F  1               ; If a slot matches CurrentObjectIndex, restart selected-object processing at
00DD4F  1               ; $DCE0 with the matching slot index still in X.
00DD4F  1               ; ----------------------------------------------------------------------------
00DD4F  1               
00DD4F  1  A2 04            ldx #$04                    ; $DD4F: A2 04
00DD51  1               
00DD51  1               ObjectSelection_SearchSlots:    ; $DD51
00DD51  1  D5 A4            cmp $A4,x                   ; $DD51: D5 A4
00DD53  1  F0 8B            beq ProcessSelectedObject   ; $DD53: F0 8B
00DD55  1               
00DD55  1  CA               dex                         ; $DD55: CA
00DD56  1  D0 F9            bne ObjectSelection_SearchSlots
00DD58  1                                               ; $DD56: D0 F9
00DD58  1               
00DD58  1               ; ----------------------------------------------------------------------------
00DD58  1               ; If BaseMotionEventCount or SpecialSequenceState is nonzero, continue at the shared state path
00DD58  1               ; beginning at $DD78.
00DD58  1               ; ----------------------------------------------------------------------------
00DD58  1               
00DD58  1  A6 5E            ldx BaseMotionEventCount        ; $DD58: A6 5E
00DD5A  1  D0 1C            bne ObjectSelection_NoSavedObject
00DD5C  1                                               ; $DD5A: D0 1C
00DD5C  1               
00DD5C  1  A6 6D            ldx SpecialSequenceState                 ; $DD5C: A6 6D
00DD5E  1  D0 18            bne ObjectSelection_NoSavedObject
00DD60  1                                               ; $DD5E: D0 18
00DD60  1               
00DD60  1               ; ----------------------------------------------------------------------------
00DD60  1               ; Run the geometry/collision test at $CBEA.
00DD60  1               ;
00DD60  1               ; Carry clear continues locally. Carry set transfers to the alternate path at
00DD60  1               ; $DED8.
00DD60  1               ; ----------------------------------------------------------------------------
00DD60  1               
00DD60  1  20 EA CB         jsr TestCurrentObjectCollision                   ; $DD60: 20 EA CB
00DD63  1  90 03            bcc ObjectSelection_CheckCurrent
00DD65  1                                               ; $DD63: 90 03
00DD65  1               
00DD65  1  4C D8 DE         jmp ObjectRouting_ReverseMovement                   ; $DD65: 4C D8 DE
00DD68  1               
00DD68  1               ; ----------------------------------------------------------------------------
00DD68  1               ; Compare CurrentObjectIndex against the primary and saved object offsets.
00DD68  1               ; ----------------------------------------------------------------------------
00DD68  1               
00DD68  1               ObjectSelection_CheckCurrent:   ; $DD68
00DD68  1  A6 E1            ldx CurrentObjectIndex      ; $DD68: A6 E1
00DD6A  1               
00DD6A  1  E4 A4            cpx $A4                     ; $DD6A: E4 A4
00DD6C  1  F0 71            beq ObjectRouting_CheckBaseState                   ; $DD6C: F0 71
00DD6E  1               
00DD6E  1  E4 A9            cpx $A9                     ; $DD6E: E4 A9
00DD70  1  F0 10            beq ObjectSelection_CheckActive
00DD72  1                                               ; $DD70: F0 10
00DD72  1               
00DD72  1               ; ----------------------------------------------------------------------------
00DD72  1               ; If no saved object exists, branch forward to $DDC8.
00DD72  1               ;
00DD72  1               ; Otherwise, restart the available-slot search at $DD21.
00DD72  1               ; ----------------------------------------------------------------------------
00DD72  1               
00DD72  1  A5 A9            lda $A9                     ; $DD72: A5 A9
00DD74  1  F0 52            beq ObjectRoutingPath                   ; $DD74: F0 52
00DD76  1               
00DD76  1  D0 A9            bne FindAvailableObjectSlot ; $DD76: D0 A9
00DD78  1                                               ; Always taken when A is nonzero.
00DD78  1               
00DD78  1               ; ============================================================================
00DD78  1               ; $DD78-$DD8E
00DD78  1               ; Exit path followed by the shared object-selection continuation.
00DD78  1               ; ============================================================================
00DD78  1               
00DD78  1               ObjectSelection_NoSavedObject:  ; $DD78
00DD78  1  20 D3 E2         jsr ClearCurrentObjectMovement                   ; $DD78: 20 D3 E2
00DD7B  1  4C 6A EB         jmp CommonEngineExit                   ; $DD7B: 4C 6A EB
00DD7E  1               
00DD7E  1               ; ----------------------------------------------------------------------------
00DD7E  1               ; Continue according to the flags returned by the preceding shared helper.
00DD7E  1               ;
00DD7E  1               ; These branches go backward into previously decoded code:
00DD7E  1               ;
00DD7E  1               ;   Z set   -> assign the current object to an available slot at $DD3C
00DD7E  1               ;   C clear -> restart the slot-selection routine at $DD21
00DD7E  1               ; ----------------------------------------------------------------------------
00DD7E  1               
00DD7E  1               ObjectSelection_StatePath:      ; $DD7E
00DD7E  1  F0 BC            beq AssignObjectToSlot      ; $DD7E: F0 BC
00DD80  1               ObjectSelection_RestartSlots:
00DD80  1  90 9F            bcc FindAvailableObjectSlot ; $DD80: 90 9F
00DD82  1               
00DD82  1               ; ----------------------------------------------------------------------------
00DD82  1               ; Check whether an object is already active in $A4.
00DD82  1               ;
00DD82  1               ; This is also the target of the BEQ at $DD34:
00DD82  1               ;
00DD82  1               ;   $DD34: F0 4C -> $DD82
00DD82  1               ; ----------------------------------------------------------------------------
00DD82  1               
00DD82  1               ObjectSelection_CheckActive:    ; $DD82
00DD82  1  A6 A4            ldx $A4                     ; $DD82: A6 A4
00DD84  1  D0 09            bne ProcessSavedObjectGeometry
00DD86  1                                               ; $DD84: D0 09
00DD86  1               
00DD86  1               ; ----------------------------------------------------------------------------
00DD86  1               ; No active object is stored in $A4.
00DD86  1               ;
00DD86  1               ; X is zero here, so clear $A9, then assign CurrentObjectIndex to $A4.
00DD86  1               ; ----------------------------------------------------------------------------
00DD86  1               
00DD86  1  86 A9            stx $A9                     ; $DD86: 86 A9
00DD88  1               
00DD88  1               HandleSavedObject:              ; $DD88
00DD88  1  A6 E1            ldx CurrentObjectIndex      ; $DD88: A6 E1
00DD8A  1  86 A4            stx $A4                     ; $DD8A: 86 A4
00DD8C  1               
00DD8C  1  4C 48 DD         jmp ContinueObjectProcessing
00DD8F  1                                               ; $DD8C: 4C 48 DD
00DD8F  1               
00DD8F  1               ; ============================================================================
00DD8F  1               ; $DD8F-$DDC7
00DD8F  1               ; Build and test a geometry region around the active object.
00DD8F  1               ;
00DD8F  1               ; Entry:
00DD8F  1               ;   X = active object offset loaded from $A4
00DD8F  1               ;
00DD8F  1               ; The object's coordinate is copied into the geometry arguments at $B2-$B5.
00DD8F  1               ; The vertical high byte is increased by five before the geometry test.
00DD8F  1               ; ============================================================================
00DD8F  1               
00DD8F  1               ProcessSavedObjectGeometry:      ; $DD8F
00DD8F  1  BD 09 05         lda $0509,x                 ; $DD8F: BD 09 05
00DD92  1  85 B2            sta $B2                     ; $DD92: 85 B2
00DD94  1               
00DD94  1  BD 0A 05         lda $050A,x                 ; $DD94: BD 0A 05
00DD97  1  85 B3            sta $B3                     ; $DD97: 85 B3
00DD99  1               
00DD99  1  BD 3A 05         lda $053A,x                 ; $DD99: BD 3A 05
00DD9C  1  85 B4            sta $B4                     ; $DD9C: 85 B4
00DD9E  1               
00DD9E  1  BD 3B 05         lda $053B,x                 ; $DD9E: BD 3B 05
00DDA1  1  18               clc                         ; $DDA1: 18
00DDA2  1  69 05            adc #$05                    ; $DDA2: 69 05
00DDA4  1  85 B5            sta $B5                     ; $DDA4: 85 B5
00DDA6  1               
00DDA6  1               ; ----------------------------------------------------------------------------
00DDA6  1               ; Adjust the geometry arguments and perform the region test.
00DDA6  1               ; ----------------------------------------------------------------------------
00DDA6  1               
00DDA6  1  20 FB DE         jsr SelectObjectGeometrySize                   ; $DDA6: 20 FB DE
00DDA9  1  20 62 E5         jsr EvaluateLoadedCurrentObjectGeometry                   ; $DDA9: 20 62 E5
00DDAC  1               
00DDAC  1  90 06            bcc ProcessSavedObjectAnimation
00DDAE  1                                               ; $DDAC: 90 06
00DDAE  1               
00DDAE  1               ; ----------------------------------------------------------------------------
00DDAE  1               ; Region test remains active.
00DDAE  1               ;
00DDAE  1               ; Run the setup helper and continue using the delay returned in A.
00DDAE  1               ; ----------------------------------------------------------------------------
00DDAE  1               
00DDAE  1  20 DE E2         jsr UpdateCurrentObjectAnimationDelay                   ; $DDAE: 20 DE E2
00DDB1  1               
00DDB1  1  4C 4A DD         jmp ContinueObjectProcessingWithDelay
00DDB4  1                                               ; $DDB1: 4C 4A DD
00DDB4  1               
00DDB4  1               ; ----------------------------------------------------------------------------
00DDB4  1               ; Region test cleared.
00DDB4  1               ;
00DDB4  1               ; Set the current object's animation frame to $67. Compact object indices
00DDB4  1               ; below $0C also receive attribute/state value $43.
00DDB4  1               ; ----------------------------------------------------------------------------
00DDB4  1               
00DDB4  1               ProcessSavedObjectAnimation:    ; $DDB4
00DDB4  1  20 68 DA         jsr GetCurrentObjectStateIndex
00DDB7  1                                               ; $DDB4: 20 68 DA
00DDB7  1               
00DDB7  1  A9 67            lda #$67                    ; $DDB7: A9 67
00DDB9  1  9D 9B 03         sta $039B,x                 ; $DDB9: 9D 9B 03
00DDBC  1               
00DDBC  1  E0 0C            cpx #$0C                    ; $DDBC: E0 0C
00DDBE  1  B0 05            bcs ProcessSavedObjectAnimation_Done
00DDC0  1                                               ; $DDBE: B0 05
00DDC0  1               
00DDC0  1  A9 43            lda #$43                    ; $DDC0: A9 43
00DDC2  1  9D B0 03         sta $03B0,x                 ; $DDC2: 9D B0 03
00DDC5  1               
00DDC5  1               ProcessSavedObjectAnimation_Done: ; $DDC5
00DDC5  1  4C 48 DD         jmp ContinueObjectProcessing
00DDC8  1                                               ; $DDC5: 4C 48 DD
00DDC8  1               
00DDC8  1               ; ============================================================================
00DDC8  1               ; $DDC8-$DE54
00DDC8  1               ; Route the current object through slot selection, state checks, animation
00DDC8  1               ; setup, collision tests, and common continuation paths.
00DDC8  1               ; ============================================================================
00DDC8  1               
00DDC8  1               ObjectRoutingPath:              ; $DDC8
00DDC8  1  A0 16            ldy #$16                    ; $DDC8: A0 16
00DDCA  1               
00DDCA  1               ; ----------------------------------------------------------------------------
00DDCA  1               ; Object offsets above $16 skip directly to the main state check at $DDDF.
00DDCA  1               ; ----------------------------------------------------------------------------
00DDCA  1               
00DDCA  1  C4 E1            cpy CurrentObjectIndex      ; $DDCA: C4 E1
00DDCC  1  90 11            bcc ObjectRouting_CheckBaseState
00DDCE  1                                               ; $DDCC: 90 11
00DDCE  1               
00DDCE  1               ; ----------------------------------------------------------------------------
00DDCE  1               ; Search zero-page object slots $A8 through $A5.
00DDCE  1               ;
00DDCE  1               ; An empty slot branches backward to ObjectSelection_StatePath at $DD7E.
00DDCE  1               ; ----------------------------------------------------------------------------
00DDCE  1               
00DDCE  1  A2 04            ldx #$04                    ; $DDCE: A2 04
00DDD0  1               
00DDD0  1               ObjectRouting_SearchSlots:      ; $DDD0
00DDD0  1  B5 A4            lda $A4,x                   ; $DDD0: B5 A4
00DDD2  1  F0 AA            beq ObjectSelection_StatePath
00DDD4  1                                               ; $DDD2: F0 AA
00DDD4  1               
00DDD4  1  CA               dex                         ; $DDD4: CA
00DDD5  1  D0 F9            bne ObjectRouting_SearchSlots
00DDD7  1                                               ; $DDD5: D0 F9
00DDD7  1               
00DDD7  1               ; ----------------------------------------------------------------------------
00DDD7  1               ; Compare the limit value $16 against the active and saved object offsets.
00DDD7  1               ;
00DDD7  1               ; If Y is below either offset, branch backward to the BCC at $DD80, which
00DDD7  1               ; restarts the available-slot routine at $DD21.
00DDD7  1               ; ----------------------------------------------------------------------------
00DDD7  1               
00DDD7  1  C4 A4            cpy $A4                     ; $DDD7: C4 A4
00DDD9  1  90 A5            bcc ObjectSelection_RestartSlots
00DDDB  1                                               ; $DDD9: 90 A5
00DDDB  1               
00DDDB  1  C4 A9            cpy $A9                     ; $DDDB: C4 A9
00DDDD  1  90 A1            bcc ObjectSelection_RestartSlots
00DDDF  1                                               ; $DDDD: 90 A1
00DDDF  1               
00DDDF  1               ; ============================================================================
00DDDF  1               ; $DDDF
00DDDF  1               ; Main state and candidate-selection path.
00DDDF  1               ; ============================================================================
00DDDF  1               
00DDDF  1               ObjectRouting_CheckBaseState:   ; $DDDF
00DDDF  1  AD 6C 05         lda $056C                   ; $DDDF: AD 6C 05
00DDE2  1  C9 03            cmp #$03                    ; $DDE2: C9 03
00DDE4  1  10 6F            bpl ObjectRouting_BaseStateAtLeast3
00DDE6  1                                               ; $DDE4: 10 6F
00DDE6  1                                               ; Target $DE55.
00DDE6  1               
00DDE6  1               ; ----------------------------------------------------------------------------
00DDE6  1               ; Obtain a candidate through $DF45.
00DDE6  1               ; ----------------------------------------------------------------------------
00DDE6  1               
00DDE6  1  20 45 DF         jsr CalculateCurrentObjectGeometry                   ; $DDE6: 20 45 DF
00DDE9  1               
00DDE9  1  C9 18            cmp #$18                    ; $DDE9: C9 18
00DDEB  1  B0 08            bcs ObjectRouting_CheckCandidate8
00DDED  1                                               ; $DDEB: B0 08
00DDED  1               
00DDED  1               ; ----------------------------------------------------------------------------
00DDED  1               ; For candidates below $18, distinguish current object offsets below or above
00DDED  1               ; $18 before applying the candidate-$08 threshold.
00DDED  1               ; ----------------------------------------------------------------------------
00DDED  1               
00DDED  1  A6 E1            ldx CurrentObjectIndex      ; $DDED: A6 E1
00DDEF  1  E0 18            cpx #$18                    ; $DDEF: E0 18
00DDF1  1  B0 04            bcs ObjectRouting_CompareCurrent
00DDF3  1                                               ; $DDF1: B0 04
00DDF3  1               
00DDF3  1  C9 08            cmp #$08                    ; $DDF3: C9 08
00DDF5  1               
00DDF5  1               ObjectRouting_CheckCandidate8:  ; $DDF5
00DDF5  1  B0 78            bcs ObjectRouting_LargeCandidate
00DDF7  1                                               ; $DDF5: B0 78
00DDF7  1                                               ; Target $DE6F.
00DDF7  1               
00DDF7  1               ; ----------------------------------------------------------------------------
00DDF7  1               ; Candidate is below the active threshold.
00DDF7  1               ;
00DDF7  1               ; If CurrentObjectIndex differs from $A4, run the alternate path at $DE4D.
00DDF7  1               ; ----------------------------------------------------------------------------
00DDF7  1               
00DDF7  1               ObjectRouting_CompareCurrent:   ; $DDF7
00DDF7  1  A6 E1            ldx CurrentObjectIndex      ; $DDF7: A6 E1
00DDF9  1  E4 A4            cpx $A4                     ; $DDF9: E4 A4
00DDFB  1  D0 50            bne ObjectRouting_Alternate ; $DDFB: D0 50
00DDFD  1               
00DDFD  1  C9 02            cmp #$02                    ; $DDFD: C9 02
00DDFF  1  B0 77            bcs ObjectRouting_ApplyCoordinateSetup
00DE01  1                                               ; $DDFF: B0 77
00DE01  1                                               ; Target $DE78.
00DE01  1               
00DE01  1               ; ----------------------------------------------------------------------------
00DE01  1               ; Configure animation values for candidate values zero or one.
00DE01  1               ; ----------------------------------------------------------------------------
00DE01  1               
00DE01  1  20 68 DA         jsr GetCurrentObjectStateIndex
00DE04  1                                               ; $DE01: 20 68 DA
00DE04  1               
00DE04  1  A9 3E            lda #$3E                    ; $DE04: A9 3E
00DE06  1  AC 6C 05         ldy $056C                   ; $DE06: AC 6C 05
00DE09  1  F0 0B            beq ObjectRouting_UseFrame60
00DE0B  1                                               ; $DE09: F0 0B
00DE0B  1               
00DE0B  1  A9 43            lda #$43                    ; $DE0B: A9 43
00DE0D  1               
00DE0D  1  88               dey                         ; $DE0D: 88
00DE0E  1  D0 06            bne ObjectRouting_UseFrame60
00DE10  1                                               ; $DE0E: D0 06
00DE10  1               
00DE10  1  A9 41            lda #$41                    ; $DE10: A9 41
00DE12  1  A0 5E            ldy #$5E                    ; $DE12: A0 5E
00DE14  1  D0 02            bne ObjectRouting_SaveFrames
00DE16  1                                               ; $DE14: D0 02
00DE16  1               
00DE16  1               ObjectRouting_UseFrame60:       ; $DE16
00DE16  1  A0 60            ldy #$60                    ; $DE16: A0 60
00DE18  1               
00DE18  1               ObjectRouting_SaveFrames:       ; $DE18
00DE18  1  E0 0C            cpx #$0C                    ; $DE18: E0 0C
00DE1A  1  B0 03            bcs ObjectRouting_SaveMainFrame
00DE1C  1                                               ; $DE1A: B0 03
00DE1C  1               
00DE1C  1  9D B0 03         sta $03B0,x                 ; $DE1C: 9D B0 03
00DE1F  1               
00DE1F  1               ObjectRouting_SaveMainFrame:    ; $DE1F
00DE1F  1  98               tya                         ; $DE1F: 98
00DE20  1  9D 9B 03         sta $039B,x                 ; $DE20: 9D 9B 03
00DE23  1               
00DE23  1               ; ----------------------------------------------------------------------------
00DE23  1               ; Run the base-object merge/comparison helper.
00DE23  1               ;
00DE23  1               ; Failure returns a one-tick delay through the shared path at $DD4A.
00DE23  1               ; ----------------------------------------------------------------------------
00DE23  1               
00DE23  1  A6 E1            ldx CurrentObjectIndex      ; $DE23: A6 E1
00DE25  1  20 C0 C9         jsr TryMergeObjectIntoBase            ; $DE25: 20 C0 C9
00DE28  1               
00DE28  1  F0 05            beq ObjectRouting_MergeSucceeded
00DE2A  1                                               ; $DE28: F0 05
00DE2A  1               
00DE2A  1  A9 01            lda #$01                    ; $DE2A: A9 01
00DE2C  1  4C 4A DD         jmp ContinueObjectProcessingWithDelay
00DE2F  1                                               ; $DE2C: 4C 4A DD
00DE2F  1               
00DE2F  1               ; ----------------------------------------------------------------------------
00DE2F  1               ; Merge succeeded. Advance engine and motion state.
00DE2F  1               ; ----------------------------------------------------------------------------
00DE2F  1               
00DE2F  1               ObjectRouting_MergeSucceeded:   ; $DE2F
00DE2F  1  20 D3 E2         jsr ClearCurrentObjectMovement                   ; $DE2F: 20 D3 E2
00DE32  1  20 E6 E3         jsr InitializeBaseObjectFromCurrent                   ; $DE32: 20 E6 E3
00DE35  1               
00DE35  1  E6 5E            inc BaseMotionEventCount        ; $DE35: E6 5E
00DE37  1               
00DE37  1  A9 20            lda #$20                    ; $DE37: A9 20
00DE39  1  85 FE            sta PendingAudioFlags             ; $DE39: 85 FE
00DE3B  1               
00DE3B  1  A5 5D            lda BaseMotionPhase             ; $DE3B: A5 5D
00DE3D  1  D0 03            bne ObjectRouting_TestRegion
00DE3F  1                                               ; $DE3D: D0 03
00DE3F  1               
00DE3F  1  20 5A E3         jsr ProcessCompactObjectState_FindAlternate                   ; $DE3F: 20 5A E3
00DE42  1               
00DE42  1               ; ----------------------------------------------------------------------------
00DE42  1               ; Test the current object's region.
00DE42  1               ;
00DE42  1               ; Carry set routes to $DED8. Carry clear enters the engine path at $E037.
00DE42  1               ; ----------------------------------------------------------------------------
00DE42  1               
00DE42  1               ObjectRouting_TestRegion:       ; $DE42
00DE42  1  20 EA CB         jsr TestCurrentObjectCollision                   ; $DE42: 20 EA CB
00DE45  1  90 03            bcc ObjectRouting_EnterEngine
00DE47  1                                               ; $DE45: 90 03
00DE47  1               
00DE47  1  4C D8 DE         jmp ObjectRouting_ReverseMovement                   ; $DE47: 4C D8 DE
00DE4A  1               
00DE4A  1               ObjectRouting_EnterEngine:      ; $DE4A
00DE4A  1  4C 37 E0         jmp ObjectStateDispatch                   ; $DE4A: 4C 37 E0
00DE4D  1               
00DE4D  1               ; ----------------------------------------------------------------------------
00DE4D  1               ; CurrentObjectIndex differs from $A4.
00DE4D  1               ;
00DE4D  1               ; Run the helper at $DEEF and return a one-tick delay through the shared path.
00DE4D  1               ; ----------------------------------------------------------------------------
00DE4D  1               
00DE4D  1               ObjectRouting_Alternate:        ; $DE4D
00DE4D  1  20 EF DE         jsr AssignCurrentObjectSlot                   ; $DE4D: 20 EF DE
00DE50  1               
00DE50  1  A9 01            lda #$01                    ; $DE50: A9 01
00DE52  1  4C 4A DD         jmp ContinueObjectProcessingWithDelay
00DE55  1                                               ; $DE52: 4C 4A DD
00DE55  1               
00DE55  1               ; ============================================================================
00DE55  1               ; $DE55-$DE83
00DE55  1               ; Handle base state $056C >= 3.
00DE55  1               ;
00DE55  1               ; The routine obtains a candidate value from $DF08 and chooses between a
00DE55  1               ; coordinate-based setup path and the candidate-state path at $DE84.
00DE55  1               ; ============================================================================
00DE55  1               
00DE55  1               ObjectRouting_BaseStateAtLeast3: ; $DE55
00DE55  1  20 08 DF         jsr TestCurrentObjectGeometry                   ; $DE55: 20 08 DF
00DE58  1               
00DE58  1  C9 07            cmp #$07                    ; $DE58: C9 07
00DE5A  1  90 28            bcc ObjectRouting_CandidateBelow7
00DE5C  1                                               ; $DE5A: 90 28
00DE5C  1                                               ; Target $DE84.
00DE5C  1               
00DE5C  1               ; ----------------------------------------------------------------------------
00DE5C  1               ; Candidate is at least seven.
00DE5C  1               ;
00DE5C  1               ; For object offsets below $18, use the coordinate setup path directly.
00DE5C  1               ; For offsets at least $18, candidate values below $18 return to $DE84.
00DE5C  1               ; ----------------------------------------------------------------------------
00DE5C  1               
00DE5C  1  A6 E1            ldx CurrentObjectIndex      ; $DE5C: A6 E1
00DE5E  1  E0 18            cpx #$18                    ; $DE5E: E0 18
00DE60  1  90 04            bcc ObjectRouting_SetupCoordinates
00DE62  1                                               ; $DE60: 90 04
00DE62  1               
00DE62  1  C9 18            cmp #$18                    ; $DE62: C9 18
00DE64  1  90 1E            bcc ObjectRouting_CandidateBelow7
00DE66  1                                               ; $DE64: 90 1E
00DE66  1               
00DE66  1               ; ----------------------------------------------------------------------------
00DE66  1               ; Build geometry/coordinate arguments.
00DE66  1               ;
00DE66  1               ; $B5 begins at zero. $DEFB adjusts or derives the geometry values and returns
00DE66  1               ; a value in A, which is saved in $B3.
00DE66  1               ; ----------------------------------------------------------------------------
00DE66  1               
00DE66  1               ObjectRouting_SetupCoordinates: ; $DE66
00DE66  1  A9 00            lda #$00                    ; $DE66: A9 00
00DE68  1  85 B5            sta $B5                     ; $DE68: 85 B5
00DE6A  1               
00DE6A  1  20 FB DE         jsr SelectObjectGeometrySize                   ; $DE6A: 20 FB DE
00DE6D  1  85 B3            sta $B3                     ; $DE6D: 85 B3
00DE6F  1               
00DE6F  1               ; ----------------------------------------------------------------------------
00DE6F  1               ; If $A4 equals CurrentObjectIndex, clear $A4.
00DE6F  1               ; ----------------------------------------------------------------------------
00DE6F  1               ObjectRouting_LargeCandidate:
00DE6F  1  38               sec                         ; $DE6F: 38
00DE70  1               
00DE70  1  A5 A4            lda $A4                     ; $DE70: A5 A4
00DE72  1  E5 E1            sbc CurrentObjectIndex      ; $DE72: E5 E1
00DE74  1  D0 02            bne ObjectRouting_ApplyCoordinateSetup
00DE76  1                                               ; $DE74: D0 02
00DE76  1               
00DE76  1  85 A4            sta $A4                     ; $DE76: 85 A4
00DE78  1                                               ; A is zero on equality.
00DE78  1               
00DE78  1               ; ----------------------------------------------------------------------------
00DE78  1               ; Apply the geometry setup, select a delay, and continue through $DD4A.
00DE78  1               ; ----------------------------------------------------------------------------
00DE78  1               
00DE78  1               ObjectRouting_ApplyCoordinateSetup: ; $DE78
00DE78  1  20 19 E5         jsr BuildGeometryVectorFromArguments                   ; $DE78: 20 19 E5
00DE7B  1  20 28 E5         jsr StoreCurrentObjectMovement                   ; $DE7B: 20 28 E5
00DE7E  1  20 DE E2         jsr UpdateCurrentObjectAnimationDelay                   ; $DE7E: 20 DE E2
00DE81  1               
00DE81  1  4C 4A DD         jmp ContinueObjectProcessingWithDelay
00DE84  1                                               ; $DE81: 4C 4A DD
00DE84  1               
00DE84  1               ; ============================================================================
00DE84  1               ; $DE84-$DEC7
00DE84  1               ; Handle candidate values below the high-state routing threshold.
00DE84  1               ; ============================================================================
00DE84  1               
00DE84  1               ObjectRouting_CandidateBelow7:  ; $DE84
00DE84  1  C9 02            cmp #$02                    ; $DE84: C9 02
00DE86  1  90 40            bcc ObjectRouting_CandidateBelow2
00DE88  1                                               ; $DE86: 90 40
00DE88  1                                               ; Target $DEC8.
00DE88  1               
00DE88  1               ; ----------------------------------------------------------------------------
00DE88  1               ; Candidate is at least two.
00DE88  1               ;
00DE88  1               ; CurrentObjectIndex must match either $A4 or $A9. Otherwise, return to the
00DE88  1               ; alternate path at $DE4D.
00DE88  1               ; ----------------------------------------------------------------------------
00DE88  1               
00DE88  1  A6 E1            ldx CurrentObjectIndex      ; $DE88: A6 E1
00DE8A  1               
00DE8A  1  E4 A4            cpx $A4                     ; $DE8A: E4 A4
00DE8C  1  F0 04            beq ObjectRouting_SetCandidateAnimation
00DE8E  1                                               ; $DE8C: F0 04
00DE8E  1               
00DE8E  1  E4 A9            cpx $A9                     ; $DE8E: E4 A9
00DE90  1  D0 BB            bne ObjectRouting_Alternate ; $DE90: D0 BB
00DE92  1               
00DE92  1               ; ----------------------------------------------------------------------------
00DE92  1               ; Assign animation frame $5E and an attribute/state value of $41 or $42.
00DE92  1               ; ----------------------------------------------------------------------------
00DE92  1               
00DE92  1               ObjectRouting_SetCandidateAnimation: ; $DE92
00DE92  1  20 68 DA         jsr GetCurrentObjectStateIndex
00DE95  1                                               ; $DE92: 20 68 DA
00DE95  1               
00DE95  1  A9 5E            lda #$5E                    ; $DE95: A9 5E
00DE97  1  9D 9B 03         sta $039B,x                 ; $DE97: 9D 9B 03
00DE9A  1               
00DE9A  1  E0 0C            cpx #$0C                    ; $DE9A: E0 0C
00DE9C  1  B0 0C            bcs ObjectRouting_UpdateCandidate
00DE9E  1                                               ; $DE9C: B0 0C
00DE9E  1               
00DE9E  1  A9 41            lda #$41                    ; $DE9E: A9 41
00DEA0  1               
00DEA0  1  DD B0 03         cmp $03B0,x                 ; $DEA0: DD B0 03
00DEA3  1  D0 02            bne ObjectRouting_SaveCandidateAttribute
00DEA5  1                                               ; $DEA3: D0 02
00DEA5  1               
00DEA5  1  A9 42            lda #$42                    ; $DEA5: A9 42
00DEA7  1               
00DEA7  1               ObjectRouting_SaveCandidateAttribute: ; $DEA7
00DEA7  1  9D B0 03         sta $03B0,x                 ; $DEA7: 9D B0 03
00DEAA  1               
00DEAA  1               ; ----------------------------------------------------------------------------
00DEAA  1               ; Update the current object and attempt the base-object merge.
00DEAA  1               ; ----------------------------------------------------------------------------
00DEAA  1               
00DEAA  1               ObjectRouting_UpdateCandidate:  ; $DEAA
00DEAA  1  A6 E1            ldx CurrentObjectIndex      ; $DEAA: A6 E1
00DEAC  1  20 B7 E6         jsr ClearMovementTransforms                   ; $DEAC: 20 B7 E6
00DEAF  1               
00DEAF  1  A6 E1            ldx CurrentObjectIndex      ; $DEAF: A6 E1
00DEB1  1  20 C0 C9         jsr TryMergeObjectIntoBase            ; $DEB1: 20 C0 C9
00DEB4  1               
00DEB4  1  F0 1F            beq ObjectRouting_MergeComplete
00DEB6  1                                               ; $DEB4: F0 1F
00DEB6  1                                               ; Target $DED5.
00DEB6  1               
00DEB6  1               ; ----------------------------------------------------------------------------
00DEB6  1               ; Merge did not complete.
00DEB6  1               ;
00DEB6  1               ; Rebuild geometry arguments and return through the shared continuation.
00DEB6  1               ; ----------------------------------------------------------------------------
00DEB6  1               
00DEB6  1  A9 00            lda #$00                    ; $DEB6: A9 00
00DEB8  1  85 B5            sta $B5                     ; $DEB8: 85 B5
00DEBA  1               
00DEBA  1  20 FB DE         jsr SelectObjectGeometrySize                   ; $DEBA: 20 FB DE
00DEBD  1  85 B3            sta $B3                     ; $DEBD: 85 B3
00DEBF  1               
00DEBF  1  20 19 E5         jsr BuildGeometryVectorFromArguments                   ; $DEBF: 20 19 E5
00DEC2  1  20 28 E5         jsr StoreCurrentObjectMovement                   ; $DEC2: 20 28 E5
00DEC5  1               
00DEC5  1  4C 48 DD         jmp ContinueObjectProcessing
00DEC8  1                                               ; $DEC5: 4C 48 DD
00DEC8  1               
00DEC8  1               ; ============================================================================
00DEC8  1               ; $DEC8-$DED7
00DEC8  1               ; Candidate values zero or one.
00DEC8  1               ; ============================================================================
00DEC8  1               
00DEC8  1               ObjectRouting_CandidateBelow2:  ; $DEC8
00DEC8  1  20 D3 E2         jsr ClearCurrentObjectMovement                   ; $DEC8: 20 D3 E2
00DECB  1               
00DECB  1  20 C0 C9         jsr TryMergeObjectIntoBase            ; $DECB: 20 C0 C9
00DECE  1  F0 05            beq ObjectRouting_MergeComplete
00DED0  1                                               ; $DECE: F0 05
00DED0  1               
00DED0  1  A9 01            lda #$01                    ; $DED0: A9 01
00DED2  1  4C 4A DD         jmp ContinueObjectProcessingWithDelay
00DED5  1                                               ; $DED2: 4C 4A DD
00DED5  1               
00DED5  1               ; ----------------------------------------------------------------------------
00DED5  1               ; Merge completed. Re-enter the success path at $DE2F.
00DED5  1               ; ----------------------------------------------------------------------------
00DED5  1               
00DED5  1               ObjectRouting_MergeComplete:    ; $DED5
00DED5  1  4C 2F DE         jmp ObjectRouting_MergeSucceeded
00DED8  1                                               ; $DED5: 4C 2F DE
00DED8  1               
00DED8  1               ; ============================================================================
00DED8  1               ; $DED8-$DEEE
00DED8  1               ; Region/collision response path.
00DED8  1               ;
00DED8  1               ; Negate the current object's horizontal and vertical high movement values and
00DED8  1               ; store the results in $056D,X/$056E,X.
00DED8  1               ; ============================================================================
00DED8  1               
00DED8  1               ObjectRouting_ReverseMovement:  ; $DED8
00DED8  1  A6 E1            ldx CurrentObjectIndex      ; $DED8: A6 E1
00DEDA  1               
00DEDA  1  A9 00            lda #$00                    ; $DEDA: A9 00
00DEDC  1  38               sec                         ; $DEDC: 38
00DEDD  1  FD 0A 05         sbc $050A,x                 ; $DEDD: FD 0A 05
00DEE0  1  9D 6D 05         sta $056D,x                 ; $DEE0: 9D 6D 05
00DEE3  1               
00DEE3  1  A9 00            lda #$00                    ; $DEE3: A9 00
00DEE5  1  38               sec                         ; $DEE5: 38
00DEE6  1  FD 3B 05         sbc $053B,x                 ; $DEE6: FD 3B 05
00DEE9  1  9D 6E 05         sta $056E,x                 ; $DEE9: 9D 6E 05
00DEEC  1               
00DEEC  1  4C 48 DD         jmp ContinueObjectProcessing
00DEEF  1                                               ; $DEEC: 4C 48 DD
00DEEF  1               
00DEEF  1               ; ============================================================================
00DEEF  1               ; $DEEF-$DEFA
00DEEF  1               ; Assign CurrentObjectIndex to the active or saved object slot.
00DEEF  1               ;
00DEEF  1               ; If $A4 is zero:
00DEEF  1               ;   Store CurrentObjectIndex in $A4.
00DEEF  1               ;
00DEEF  1               ; If $A4 is nonzero:
00DEEF  1               ;   Store CurrentObjectIndex in $A9.
00DEEF  1               ;
00DEEF  1               ; Return:
00DEEF  1               ;   X = CurrentObjectIndex
00DEEF  1               ; ============================================================================
00DEEF  1               
00DEEF  1               ; ----------------------------------------------------------------------------
00DEEF  1               ; Contract:
00DEEF  1               ;   Description: Implements Assign Current Object Slot.
00DEEF  1               ;   Entry: Registers: X; Memory: currentobjectindex, $a4
00DEEF  1               ;   Returns/products: Registers/clobbers: A, X
00DEEF  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00DEEF  1               ;   Memory effects: $a4
00DEEF  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00DEEF  1               ;          comparison, load, or store path and are not a stable API product.
00DEEF  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00DEEF  1               ; ----------------------------------------------------------------------------
00DEEF  1               AssignCurrentObjectSlot:        ; $DEEF
00DEEF  1  A6 E1            ldx CurrentObjectIndex      ; $DEEF: A6 E1
00DEF1  1               
00DEF1  1  A5 A4            lda $A4                     ; $DEF1: A5 A4
00DEF3  1  D0 03            bne AssignCurrentObjectToSavedSlot
00DEF5  1                                               ; $DEF3: D0 03
00DEF5  1               
00DEF5  1               ; ----------------------------------------------------------------------------
00DEF5  1               ; No active object is assigned. Store the current object in the primary slot.
00DEF5  1               ; ----------------------------------------------------------------------------
00DEF5  1               
00DEF5  1  86 A4            stx $A4                     ; $DEF5: 86 A4
00DEF7  1  60               rts                         ; $DEF7: 60
00DEF8  1               
00DEF8  1               ; ----------------------------------------------------------------------------
00DEF8  1               ; The primary slot is occupied. Store the current object in the saved slot.
00DEF8  1               ; ----------------------------------------------------------------------------
00DEF8  1               
00DEF8  1               AssignCurrentObjectToSavedSlot: ; $DEF8
00DEF8  1  86 A9            stx $A9                     ; $DEF8: 86 A9
00DEFA  1  60               rts                         ; $DEFA: 60
00DEFB  1               
00DEFB  1               ; ============================================================================
00DEFB  1               ; $DEFB-$DF07
00DEFB  1               ; Select a geometry or object-size parameter from CurrentObjectIndex.
00DEFB  1               ;
00DEFB  1               ; Return:
00DEFB  1               ;   A = selected parameter
00DEFB  1               ;   $C6 = selected parameter
00DEFB  1               ;
00DEFB  1               ; CurrentObjectIndex below $18:
00DEFB  1               ;   parameter = $08
00DEFB  1               ;
00DEFB  1               ; CurrentObjectIndex at least $18:
00DEFB  1               ;   parameter = $03
00DEFB  1               ; ============================================================================
00DEFB  1               
00DEFB  1               ; ----------------------------------------------------------------------------
00DEFB  1               ; Contract:
00DEFB  1               ;   Description: Implements Select Object Geometry Size.
00DEFB  1               ;   Entry: Registers: A, X; Memory: currentobjectindex
00DEFB  1               ;   Returns/products: Registers/clobbers: A, X
00DEFB  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00DEFB  1               ;   Memory effects: $c6
00DEFB  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00DEFB  1               ;          comparison, load, or store path and are not a stable API product.
00DEFB  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 3.
00DEFB  1               ; ----------------------------------------------------------------------------
00DEFB  1               SelectObjectGeometrySize:       ; $DEFB
00DEFB  1  A6 E1            ldx CurrentObjectIndex      ; $DEFB: A6 E1
00DEFD  1               
00DEFD  1  A9 03            lda #$03                    ; $DEFD: A9 03
00DEFF  1               
00DEFF  1  E0 18            cpx #$18                    ; $DEFF: E0 18
00DF01  1  B0 02            bcs SelectObjectGeometrySize_Save
00DF03  1                                               ; $DF01: B0 02
00DF03  1               
00DF03  1  A9 08            lda #$08                    ; $DF03: A9 08
00DF05  1               
00DF05  1               SelectObjectGeometrySize_Save:  ; $DF05
00DF05  1  85 C6            sta $C6                     ; $DF05: 85 C6
00DF07  1  60               rts                         ; $DF07: 60
00DF08  1               
00DF08  1               ; ============================================================================
00DF08  1               ; $DF08-$DF11
00DF08  1               ; Configure geometry arguments for the current object and run the region test.
00DF08  1               ;
00DF08  1               ; Return:
00DF08  1               ;   A and processor flags are returned directly from $E502.
00DF08  1               ;
00DF08  1               ; Call sequence:
00DF08  1               ;   $DF12  Select and copy the relevant object coordinates into $B2-$B5.
00DF08  1               ;   $E4DB  Process or normalize the geometry arguments.
00DF08  1               ;   $E502  Perform the final geometry/region test.
00DF08  1               ; ============================================================================
00DF08  1               
00DF08  1               ; ----------------------------------------------------------------------------
00DF08  1               ; Contract:
00DF08  1               ;   Description: Implements Test Current Object Geometry.
00DF08  1               ;   Entry: No register input inferred
00DF08  1               ;   Returns/products: No direct product inferred
00DF08  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00DF08  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00DF08  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00DF08  1               ;          comparison, load, or store path and are not a stable API product.
00DF08  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 2.
00DF08  1               ; ----------------------------------------------------------------------------
00DF08  1               TestCurrentObjectGeometry:      ; $DF08
00DF08  1  20 12 DF         jsr SetupCurrentObjectGeometry
00DF0B  1                                               ; $DF08: 20 12 DF
00DF0B  1               
00DF0B  1  20 DB E4         jsr CalculateCurrentGeometryDifference                   ; $DF0B: 20 DB E4
00DF0E  1  20 02 E5         jsr EvaluateGeometryDifference                   ; $DF0E: 20 02 E5
00DF11  1               
00DF11  1  60               rts                         ; $DF11: 60
00DF12  1               
00DF12  1               ; ============================================================================
00DF12  1               ; $DF12-$DF26
00DF12  1               ; Copy saved base coordinates into the geometry argument structure.
00DF12  1               ;
00DF12  1               ; The original ROM deliberately uses absolute addressing for zero-page
00DF12  1               ; locations $53-$56. Raw bytes are used here to prevent CA65 from shortening
00DF12  1               ; these instructions to zero-page addressing.
00DF12  1               ; ============================================================================
00DF12  1               
00DF12  1               SetupCurrentObjectGeometry:     ; $DF12
00DF12  1  AD 53 00         .byte $AD,$53,$00           ; $DF12: LDA $0053
00DF15  1  85 B2            sta $B2                     ; $DF15: 85 B2
00DF17  1               
00DF17  1  AD 54 00         .byte $AD,$54,$00           ; $DF17: LDA $0054
00DF1A  1  85 B3            sta $B3                     ; $DF1A: 85 B3
00DF1C  1               
00DF1C  1  AD 55 00         .byte $AD,$55,$00           ; $DF1C: LDA $0055
00DF1F  1  85 B4            sta $B4                     ; $DF1F: 85 B4
00DF21  1               
00DF21  1  AD 56 00         .byte $AD,$56,$00           ; $DF21: LDA $0056
00DF24  1  85 B5            sta $B5                     ; $DF24: 85 B5
00DF26  1               
00DF26  1  60               rts                         ; $DF26: 60
00DF27  1               
00DF27  1               ; ============================================================================
00DF27  1               ; $DF27-$DF3B
00DF27  1               ; Copy the base object's live coordinates into the geometry arguments.
00DF27  1               ;
00DF27  1               ; Source:
00DF27  1               ;   $0509/$050A = base horizontal coordinate
00DF27  1               ;   $053A/$053B = base vertical coordinate
00DF27  1               ;
00DF27  1               ; Destination:
00DF27  1               ;   $B2/$B3 = geometry horizontal coordinate
00DF27  1               ;   $B4/$B5 = geometry vertical coordinate
00DF27  1               ; ============================================================================
00DF27  1               
00DF27  1               ; ----------------------------------------------------------------------------
00DF27  1               ; Contract:
00DF27  1               ;   Description: Implements Setup Base Object Geometry.
00DF27  1               ;   Entry: Registers: A; Memory: $0509, $050a, $053a, $053b
00DF27  1               ;   Returns/products: Registers/clobbers: A
00DF27  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00DF27  1               ;   Memory effects: $b2, $b3, $b4, $b5
00DF27  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00DF27  1               ;          comparison, load, or store path and are not a stable API product.
00DF27  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00DF27  1               ; ----------------------------------------------------------------------------
00DF27  1               SetupBaseObjectGeometry:        ; $DF27
00DF27  1  AD 09 05         lda $0509                   ; $DF27: AD 09 05
00DF2A  1  85 B2            sta $B2                     ; $DF2A: 85 B2
00DF2C  1               
00DF2C  1  AD 0A 05         lda $050A                   ; $DF2C: AD 0A 05
00DF2F  1  85 B3            sta $B3                     ; $DF2F: 85 B3
00DF31  1               
00DF31  1  AD 3A 05         lda $053A                   ; $DF31: AD 3A 05
00DF34  1  85 B4            sta $B4                     ; $DF34: 85 B4
00DF36  1               
00DF36  1  AD 3B 05         lda $053B                   ; $DF36: AD 3B 05
00DF39  1  85 B5            sta $B5                     ; $DF39: 85 B5
00DF3B  1               
00DF3B  1  60               rts                         ; $DF3B: 60
00DF3C  1               
00DF3C  1               ; ============================================================================
00DF3C  1               ; $DF3C-$DF44
00DF3C  1               ; Prepare geometry using the base object's live coordinates, process the
00DF3C  1               ; geometry arguments, and return the resulting high coordinate in X.
00DF3C  1               ;
00DF3C  1               ; Return:
00DF3C  1               ;   X = $AF
00DF3C  1               ;
00DF3C  1               ; A and Y retain whatever values were left by $E4DB.
00DF3C  1               ; Processor flags reflect LDX $AF.
00DF3C  1               ; ============================================================================
00DF3C  1               
00DF3C  1               PrepareBaseObjectGeometry:      ; $DF3C
00DF3C  1  20 27 DF         jsr SetupBaseObjectGeometry ; $DF3C: 20 27 DF
00DF3F  1  20 DB E4         jsr CalculateCurrentGeometryDifference                   ; $DF3F: 20 DB E4
00DF42  1               
00DF42  1  A6 AF            ldx CalculatedCoordinateHigh                     ; $DF42: A6 AF
00DF44  1  60               rts                         ; $DF44: 60
00DF45  1               
00DF45  1               ; ============================================================================
00DF45  1               ; $DF45-$DF91
00DF45  1               ; Calculate geometry and movement arguments for the current object.
00DF45  1               ;
00DF45  1               ; This routine:
00DF45  1               ;   1. Selects an object-size parameter in $C6.
00DF45  1               ;   2. Prepares the base object's geometry.
00DF45  1               ;   3. Saves a geometry result in $D4/$D5.
00DF45  1               ;   4. Copies base movement values into $D6/$D7.
00DF45  1               ;   5. Calls the signed-vector helper at $E877.
00DF45  1               ;   6. Selects and installs final geometry arguments.
00DF45  1               ;   7. Tail-calls the geometry-processing helper at $E502.
00DF45  1               ; ============================================================================
00DF45  1               
00DF45  1               ; ----------------------------------------------------------------------------
00DF45  1               ; Contract:
00DF45  1               ;   Description: Calculates Current Object Geometry.
00DF45  1               ;   Entry: Registers: A, X, Y; Memory: $0508, $0539, $c6, $d4
00DF45  1               ;   Returns/products: Registers/clobbers: A, X, Y
00DF45  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00DF45  1               ;   Memory effects: $d4, $d5, $d6, $d7, $b5, $b3
00DF45  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00DF45  1               ;          comparison, load, or store path and are not a stable API product.
00DF45  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 2.
00DF45  1               ; ----------------------------------------------------------------------------
00DF45  1               CalculateCurrentObjectGeometry: ; $DF45
00DF45  1  20 FB DE         jsr SelectObjectGeometrySize
00DF48  1                                               ; $DF45: 20 FB DE
00DF48  1               
00DF48  1  20 3C DF         jsr PrepareBaseObjectGeometry
00DF4B  1                                               ; $DF48: 20 3C DF
00DF4B  1               
00DF4B  1               ; ----------------------------------------------------------------------------
00DF4B  1               ; Save the geometry result.
00DF4B  1               ;
00DF4B  1               ; PrepareBaseObjectGeometry returns:
00DF4B  1               ;   X = geometry high/result byte from $AF
00DF4B  1               ;   A = result left by $E4DB
00DF4B  1               ; ----------------------------------------------------------------------------
00DF4B  1               
00DF4B  1  86 D4            stx $D4                     ; $DF4B: 86 D4
00DF4D  1  85 D5            sta $D5                     ; $DF4D: 85 D5
00DF4F  1               
00DF4F  1               ; ----------------------------------------------------------------------------
00DF4F  1               ; Save the base movement values.
00DF4F  1               ; ----------------------------------------------------------------------------
00DF4F  1               
00DF4F  1  AE 08 05         ldx $0508                   ; $DF4F: AE 08 05
00DF52  1  86 D6            stx $D6                     ; $DF52: 86 D6
00DF54  1               
00DF54  1  AC 39 05         ldy $0539                   ; $DF54: AC 39 05
00DF57  1  84 D7            sty $D7                     ; $DF57: 84 D7
00DF59  1               
00DF59  1               ; ----------------------------------------------------------------------------
00DF59  1               ; Run the signed-vector helper.
00DF59  1               ;
00DF59  1               ; The helper returns a signed result in A/Y. A is copied to X so its sign can
00DF59  1               ; select the next path.
00DF59  1               ; ----------------------------------------------------------------------------
00DF59  1               
00DF59  1  20 77 E8         jsr NormalizeSignedVector                   ; $DF59: 20 77 E8
00DF5C  1               
00DF5C  1  AA               tax                         ; $DF5C: AA
00DF5D  1  10 1B            bpl CalculateCurrentObjectGeometry_Nonnegative
00DF5F  1                                               ; $DF5D: 10 1B
00DF5F  1               
00DF5F  1               ; ----------------------------------------------------------------------------
00DF5F  1               ; Negative-result path.
00DF5F  1               ;
00DF5F  1               ; Convert Y to its magnitude when negative, then compare it with the selected
00DF5F  1               ; object-size parameter at $C6.
00DF5F  1               ; ----------------------------------------------------------------------------
00DF5F  1               
00DF5F  1  98               tya                         ; $DF5F: 98
00DF60  1  10 05            bpl CalculateCurrentObjectGeometry_CompareMagnitude
00DF62  1                                               ; $DF60: 10 05
00DF62  1               
00DF62  1  49 FF            eor #$FF                    ; $DF62: 49 FF
00DF64  1  38               sec                         ; $DF64: 38
00DF65  1  69 00            adc #$00                    ; $DF65: 69 00
00DF67  1                                               ; With carry set, forms two's-complement
00DF67  1                                               ; magnitude: (~A) + 1.
00DF67  1               
00DF67  1               CalculateCurrentObjectGeometry_CompareMagnitude: ; $DF67
00DF67  1  C5 C6            cmp $C6                     ; $DF67: C5 C6
00DF69  1  B0 15            bcs CalculateCurrentObjectGeometry_Clamp
00DF6B  1                                               ; $DF69: B0 15
00DF6B  1               
00DF6B  1               ; ----------------------------------------------------------------------------
00DF6B  1               ; Magnitude is below the selected object size.
00DF6B  1               ;
00DF6B  1               ; Use:
00DF6B  1               ;   X = $C6
00DF6B  1               ;   $B5 = Y
00DF6B  1               ;   $B3 = $D4
00DF6B  1               ;
00DF6B  1               ; Then enter the geometry helper at $E502.
00DF6B  1               ; ----------------------------------------------------------------------------
00DF6B  1               
00DF6B  1  A6 C6            ldx $C6                     ; $DF6B: A6 C6
00DF6D  1               
00DF6D  1  98               tya                         ; $DF6D: 98
00DF6E  1  85 B5            sta $B5                     ; $DF6E: 85 B5
00DF70  1               
00DF70  1  20 A5 E8         jsr RunEightRoundTransform                   ; $DF70: 20 A5 E8
00DF73  1               
00DF73  1  A5 D4            lda $D4                     ; $DF73: A5 D4
00DF75  1  85 B3            sta $B3                     ; $DF75: 85 B3
00DF77  1               
00DF77  1               CalculateCurrentObjectGeometry_RunTest: ; $DF77
00DF77  1  4C 02 E5         jmp EvaluateGeometryDifference                   ; $DF77: 4C 02 E5
00DF7A  1               
00DF7A  1               ; ----------------------------------------------------------------------------
00DF7A  1               ; Nonnegative-result path.
00DF7A  1               ;
00DF7A  1               ; Initialize X from the selected object-size parameter and A to zero.
00DF7A  1               ; The unconditional BEQ continues at the shared argument-store path.
00DF7A  1               ; ----------------------------------------------------------------------------
00DF7A  1               
00DF7A  1               CalculateCurrentObjectGeometry_Nonnegative: ; $DF7A
00DF7A  1  A6 C6            ldx $C6                     ; $DF7A: A6 C6
00DF7C  1               
00DF7C  1  A9 00            lda #$00                    ; $DF7C: A9 00
00DF7E  1  F0 0C            beq CalculateCurrentObjectGeometry_SaveArguments
00DF80  1                                               ; $DF7E: F0 0C
00DF80  1               
00DF80  1               ; ----------------------------------------------------------------------------
00DF80  1               ; Clamp or normalize the selected object-size value.
00DF80  1               ;
00DF80  1               ; If Y is at least $80, invert $C6 and add the incoming carry.
00DF80  1               ; X is cleared before storing the resulting arguments.
00DF80  1               ; ----------------------------------------------------------------------------
00DF80  1               
00DF80  1               CalculateCurrentObjectGeometry_Clamp: ; $DF80
00DF80  1  A5 C6            lda $C6                     ; $DF80: A5 C6
00DF82  1               
00DF82  1  C0 80            cpy #$80                    ; $DF82: C0 80
00DF84  1  90 04            bcc CalculateCurrentObjectGeometry_ClearX
00DF86  1                                               ; $DF84: 90 04
00DF86  1               
00DF86  1  49 FF            eor #$FF                    ; $DF86: 49 FF
00DF88  1  69 00            adc #$00                    ; $DF88: 69 00
00DF8A  1               
00DF8A  1               CalculateCurrentObjectGeometry_ClearX: ; $DF8A
00DF8A  1  A2 00            ldx #$00                    ; $DF8A: A2 00
00DF8C  1               
00DF8C  1               CalculateCurrentObjectGeometry_SaveArguments: ; $DF8C
00DF8C  1  85 B5            sta $B5                     ; $DF8C: 85 B5
00DF8E  1  86 B3            stx $B3                     ; $DF8E: 86 B3
00DF90  1               
00DF90  1  F0 E5            beq CalculateCurrentObjectGeometry_RunTest
00DF92  1                                               ; $DF90: F0 E5
00DF92  1                                               ; Branches to $DF77 when the stored A value
00DF92  1                                               ; is zero.
00DF92  1               
00DF92  1               ; ============================================================================
00DF92  1               ; $DF92-$DFA6
00DF92  1               ; Transform X and Y independently, then add their two-byte results.
00DF92  1               ;
00DF92  1               ; Entry:
00DF92  1               ;   X = first signed input
00DF92  1               ;   Y = second signed input
00DF92  1               ;
00DF92  1               ; Exit:
00DF92  1               ;   A/Y = combined two-byte result
00DF92  1               ;
00DF92  1               ; The helper at $DFA7 returns:
00DF92  1               ;   A = low/result byte
00DF92  1               ;   X = high/result byte
00DF92  1               ; ============================================================================
00DF92  1               
00DF92  1               AddTransformedSignedValues:     ; $DF92
00DF92  1  8A               txa                         ; $DF92: 8A
00DF93  1  20 A7 DF         jsr TransformSignedValue    ; $DF93: 20 A7 DF
00DF96  1               
00DF96  1  86 06            stx $06                     ; $DF96: 86 06
00DF98  1  85 05            sta MathTemp05              ; $DF98: 85 05
00DF9A  1               
00DF9A  1  98               tya                         ; $DF9A: 98
00DF9B  1  20 A7 DF         jsr TransformSignedValue    ; $DF9B: 20 A7 DF
00DF9E  1               
00DF9E  1               ; ----------------------------------------------------------------------------
00DF9E  1               ; Add the two transformed results:
00DF9E  1               ;
00DF9E  1               ;   second high + first high -> Y
00DF9E  1               ;   second low  + first low  -> A
00DF9E  1               ; ----------------------------------------------------------------------------
00DF9E  1               
00DF9E  1  48               pha                         ; $DF9E: 48
00DF9F  1               
00DF9F  1  8A               txa                         ; $DF9F: 8A
00DFA0  1  65 06            adc $06                     ; $DFA0: 65 06
00DFA2  1  A8               tay                         ; $DFA2: A8
00DFA3  1               
00DFA3  1  68               pla                         ; $DFA3: 68
00DFA4  1  65 05            adc MathTemp05              ; $DFA4: 65 05
00DFA6  1               
00DFA6  1  60               rts                         ; $DFA6: 60
00DFA7  1               
00DFA7  1               ; ============================================================================
00DFA7  1               ; $DFA7-$DFC3
00DFA7  1               ; Convert a signed byte to its magnitude, then perform an eight-step
00DFA7  1               ; shift-and-add transformation.
00DFA7  1               ;
00DFA7  1               ; Entry:
00DFA7  1               ;   A = signed input byte
00DFA7  1               ;
00DFA7  1               ; Exit:
00DFA7  1               ;   A = transformed low byte
00DFA7  1               ;   X = transformed high/working byte from $28
00DFA7  1               ;
00DFA7  1               ; Working values:
00DFA7  1               ;   $28 = shifting multiplier/result byte
00DFA7  1               ;   $2B = absolute input value
00DFA7  1               ; ============================================================================
00DFA7  1               
00DFA7  1               ; ----------------------------------------------------------------------------
00DFA7  1               ; Contract:
00DFA7  1               ;   Description: Implements Transform Signed Value.
00DFA7  1               ;   Entry: Registers: A, X; Memory: $2b, $28
00DFA7  1               ;   Returns/products: Registers/clobbers: A, X
00DFA7  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00DFA7  1               ;   Memory effects: $28, $2b
00DFA7  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00DFA7  1               ;          comparison, load, or store path and are not a stable API product.
00DFA7  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 2.
00DFA7  1               ; ----------------------------------------------------------------------------
00DFA7  1               TransformSignedValue:           ; $DFA7
00DFA7  1  10 05            bpl TransformSignedValue_HaveMagnitude
00DFA9  1                                               ; $DFA7: 10 05
00DFA9  1               
00DFA9  1  49 FF            eor #$FF                    ; $DFA9: 49 FF
00DFAB  1  18               clc                         ; $DFAB: 18
00DFAC  1  69 01            adc #$01                    ; $DFAC: 69 01
00DFAE  1               
00DFAE  1               TransformSignedValue_HaveMagnitude: ; $DFAE
00DFAE  1  85 28            sta $28                     ; $DFAE: 85 28
00DFB0  1  85 2B            sta $2B                     ; $DFB0: 85 2B
00DFB2  1               
00DFB2  1  A9 00            lda #$00                    ; $DFB2: A9 00
00DFB4  1  A2 07            ldx #$07                    ; $DFB4: A2 07
00DFB6  1               
00DFB6  1               ; ----------------------------------------------------------------------------
00DFB6  1               ; Repeatedly shift $28 right through A.
00DFB6  1               ;
00DFB6  1               ; Whenever carry is set, add the original magnitude from $2B.
00DFB6  1               ; ----------------------------------------------------------------------------
00DFB6  1               
00DFB6  1               TransformSignedValue_Loop:      ; $DFB6
00DFB6  1  4A               lsr                         ; $DFB6: 4A
00DFB7  1  66 28            ror $28                     ; $DFB7: 66 28
00DFB9  1               
00DFB9  1  90 03            bcc TransformSignedValue_Next
00DFBB  1                                               ; $DFB9: 90 03
00DFBB  1               
00DFBB  1  18               clc                         ; $DFBB: 18
00DFBC  1  65 2B            adc $2B                     ; $DFBC: 65 2B
00DFBE  1               
00DFBE  1               TransformSignedValue_Next:      ; $DFBE
00DFBE  1  CA               dex                         ; $DFBE: CA
00DFBF  1  D0 F5            bne TransformSignedValue_Loop
00DFC1  1                                               ; $DFBF: D0 F5
00DFC1  1               
00DFC1  1  A6 28            ldx $28                     ; $DFC1: A6 28
00DFC3  1  60               rts                         ; $DFC3: 60
00DFC4  1               
00DFC4  1               ; ============================================================================
00DFC4  1               ; $DFC4-$DFD3
00DFC4  1               ; Signed coordinate-offset table.
00DFC4  1               ;
00DFC4  1               ; Eight two-byte entries are present. Interpreted as little-endian signed
00DFC4  1               ; 16-bit values:
00DFC4  1               ;
00DFC4  1               ;   $F800, $0800, $F800, $0000,
00DFC4  1               ;   $00F9, $0007, $00F9, $FE00
00DFC4  1               ;
00DFC4  1               ; Several later routines index this region through nearby or overlapping base
00DFC4  1               ; addresses, so preserving the raw byte layout is safest.
00DFC4  1               ; ============================================================================
00DFC4  1               
00DFC4  1               SignedCoordinateOffsetTable:    ; $DFC4
00DFC4  1  00 F8            .byte $00,$F8               ; $F800
00DFC6  1  00 08            .byte $00,$08               ; $0800
00DFC8  1  00 F8            .byte $00,$F8               ; $F800
00DFCA  1  00 00            .byte $00,$00               ; $0000
00DFCC  1  F9 00            .byte $F9,$00               ; $00F9
00DFCE  1  07 00            .byte $07,$00               ; $0007
00DFD0  1  F9 00            .byte $F9,$00               ; $00F9
00DFD2  1  00 FE            .byte $00,$FE               ; $FE00
00DFD4  1               
00DFD4  1               ; ============================================================================
00DFD4  1               ; $DFD4-$DFEA
00DFD4  1               ; Update the current object's animation values from the selector returned by
00DFD4  1               ; GetCurrentObjectSelectorAndState.
00DFD4  1               ;
00DFD4  1               ; The selector returned in X chooses an attribute from the four-byte table
00DFD4  1               ; immediately following the routine.
00DFD4  1               ; ============================================================================
00DFD4  1               
00DFD4  1               ; ----------------------------------------------------------------------------
00DFD4  1               ; Contract:
00DFD4  1               ;   Description: Updates Current Object Display State.
00DFD4  1               ;   Entry: Registers: A, X; Memory: $dfea, currentobjectindex
00DFD4  1               ;   Returns/products: Registers/clobbers: A, X
00DFD4  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00DFD4  1               ;   Memory effects: $03b0, $039b
00DFD4  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00DFD4  1               ;          comparison, load, or store path and are not a stable API product.
00DFD4  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00DFD4  1               ; ----------------------------------------------------------------------------
00DFD4  1               UpdateCurrentObjectDisplayState: ; $DFD4
00DFD4  1  20 DC E3         jsr GetCurrentObjectSelectorAndState                   ; $DFD4: 20 DC E3
00DFD7  1               
00DFD7  1               ; ----------------------------------------------------------------------------
00DFD7  1               ; Convert the returned object/event offset into a compact sprite-array index.
00DFD7  1               ; ----------------------------------------------------------------------------
00DFD7  1               
00DFD7  1  8A               txa                         ; $DFD7: 8A
00DFD8  1  4A               lsr                         ; $DFD8: 4A
00DFD9  1  AA               tax                         ; $DFD9: AA
00DFDA  1               
00DFDA  1               ; ----------------------------------------------------------------------------
00DFDA  1               ; Load the selector-dependent animation attribute.
00DFDA  1               ;
00DFDA  1               ; Y is returned by GetCurrentObjectSelectorAndState and selects one of the table entries at $DFEB.
00DFDA  1               ; ----------------------------------------------------------------------------
00DFDA  1               
00DFDA  1  B9 EA DF         lda $DFEA,y                 ; $DFDA: B9 EA DF
00DFDD  1                                               ; Original indexed base is $DFEA, one byte
00DFDD  1                                               ; before the visible table.
00DFDD  1               
00DFDD  1  9D B0 03         sta $03B0,x                 ; $DFDD: 9D B0 03
00DFE0  1               
00DFE0  1  A9 5A            lda #$5A                    ; $DFE0: A9 5A
00DFE2  1  9D 9B 03         sta $039B,x                 ; $DFE2: 9D 9B 03
00DFE5  1               
00DFE5  1               ; ----------------------------------------------------------------------------
00DFE5  1               ; Update the current object and return.
00DFE5  1               ; ----------------------------------------------------------------------------
00DFE5  1               
00DFE5  1  A6 E1            ldx CurrentObjectIndex      ; $DFE5: A6 E1
00DFE7  1  20 B7 E6         jsr ClearMovementTransforms                   ; $DFE7: 20 B7 E6
00DFEA  1               
00DFEA  1  60               rts                         ; $DFEA: 60
00DFEB  1               
00DFEB  1               ; ============================================================================
00DFEB  1               ; $DFEB-$DFEE
00DFEB  1               ; Object-display attribute table.
00DFEB  1               ;
00DFEB  1               ; The load at $DFDA intentionally uses base $DFEA. Expected Y values are
00DFEB  1               ; therefore $01-$04:
00DFEB  1               ;
00DFEB  1               ;   Y=$01 -> $DFEB
00DFEB  1               ;   Y=$02 -> $DFEC
00DFEB  1               ;   Y=$03 -> $DFED
00DFEB  1               ;   Y=$04 -> $DFEE
00DFEB  1               ; ============================================================================
00DFEB  1               
00DFEB  1               ObjectDisplayAttributeTable:    ; $DFEB
00DFEB  1  2A 3D 3D 13      .byte $2A,$3D,$3D,$13
00DFEF  1               
00DFEF  1               ; ============================================================================
00DFEF  1               ; $DFEF-$E01C
00DFEF  1               ; Assign a state value to the current object, perform a geometry test, and
00DFEF  1               ; either restart the test or finish the object transition.
00DFEF  1               ;
00DFEF  1               ; Multiple entry points select state values one through five in Y.
00DFEF  1               ; ============================================================================
00DFEF  1               
00DFEF  1               SetCurrentObjectState1:         ; $DFEF
00DFEF  1  A0 01            ldy #$01                    ; $DFEF: A0 01
00DFF1  1  D0 0E            bne SetCurrentObjectState   ; $DFF1: D0 0E
00DFF3  1               
00DFF3  1               SetCurrentObjectState2:         ; $DFF3
00DFF3  1  A0 02            ldy #$02                    ; $DFF3: A0 02
00DFF5  1  D0 0A            bne SetCurrentObjectState   ; $DFF5: D0 0A
00DFF7  1               
00DFF7  1               SetCurrentObjectState3:         ; $DFF7
00DFF7  1  A0 03            ldy #$03                    ; $DFF7: A0 03
00DFF9  1  D0 06            bne SetCurrentObjectState   ; $DFF9: D0 06
00DFFB  1               
00DFFB  1               SetCurrentObjectState4:         ; $DFFB
00DFFB  1  A0 04            ldy #$04                    ; $DFFB: A0 04
00DFFD  1  D0 02            bne SetCurrentObjectState   ; $DFFD: D0 02
00DFFF  1               
00DFFF  1               SetCurrentObjectState5:         ; $DFFF
00DFFF  1  A0 05            ldy #$05                    ; $DFFF: A0 05
00E001  1               
00E001  1               ; ----------------------------------------------------------------------------
00E001  1               ; Store the selected state in $0595 using the compact current-object index.
00E001  1               ; ----------------------------------------------------------------------------
00E001  1               
00E001  1               SetCurrentObjectState:          ; $E001
00E001  1  A5 E1            lda CurrentObjectIndex      ; $E001: A5 E1
00E003  1  4A               lsr                         ; $E003: 4A
00E004  1  AA               tax                         ; $E004: AA
00E005  1               
00E005  1  98               tya                         ; $E005: 98
00E006  1  9D 95 05         sta $0595,x                 ; $E006: 9D 95 05
00E009  1               
00E009  1               ; ----------------------------------------------------------------------------
00E009  1               ; Prepare and test the current object's geometry.
00E009  1               ; ----------------------------------------------------------------------------
00E009  1               
00E009  1               SetCurrentObjectState_Retry:    ; $E009
00E009  1  20 74 E4         jsr SelectGeometryRecord_Default                   ; $E009: 20 74 E4
00E00C  1  20 5F E5         jsr ApplyCurrentObjectGeometry                   ; $E00C: 20 5F E5
00E00F  1               
00E00F  1  90 06            bcc SetCurrentObjectState_Finish
00E011  1                                               ; $E00F: 90 06
00E011  1               
00E011  1               ; ----------------------------------------------------------------------------
00E011  1               ; Geometry remains active. Run the helper at $E313 and retry.
00E011  1               ; ----------------------------------------------------------------------------
00E011  1               
00E011  1  20 13 E3         jsr UpdateCurrentObjectAnimationAndWait                   ; $E011: 20 13 E3
00E014  1               
00E014  1  4C 09 E0         jmp SetCurrentObjectState_Retry
00E017  1                                               ; $E014: 4C 09 E0
00E017  1               
00E017  1               ; ----------------------------------------------------------------------------
00E017  1               ; Geometry cleared. Update display state and leave through the common exit.
00E017  1               ; ----------------------------------------------------------------------------
00E017  1               
00E017  1               SetCurrentObjectState_Finish:   ; $E017
00E017  1  20 D4 DF         jsr UpdateCurrentObjectDisplayState
00E01A  1                                               ; $E017: 20 D4 DF
00E01A  1               
00E01A  1  4C 6A EB         jmp CommonEngineExit                   ; $E01A: 4C 6A EB
00E01D  1               
00E01D  1               ; ============================================================================
00E01D  1               ; $E01D-$E036
00E01D  1               ; Lookup data used by the following object-state routines.
00E01D  1               ;
00E01D  1               ; Several later routines reference addresses inside this region, including
00E01D  1               ; $E021 and $E027. Preserve the exact raw layout until all references have
00E01D  1               ; been fully characterized.
00E01D  1               ; ============================================================================
00E01D  1               
00E01D  1               ObjectStateLookupData:          ; $E01D
00E01D  1  02 06 08 04      .byte $02,$06,$08,$04
00E021  1               ObjectStateThresholdTable:
00E021  1  02 05 FD FB      .byte $02,$05,$FD,$FB
00E025  1  05 FD            .byte $05,$FD
00E027  1               ObjectStateResultTable:
00E027  1  F9 00            .byte $F9,$00
00E029  1  00 FF 04 04      .byte $00,$FF,$04,$04
00E02D  1  02 04 06 06      .byte $02,$04,$06,$06
00E031  1  04 06 08 06      .byte $04,$06,$08,$06
00E035  1  08 08            .byte $08,$08
00E037  1               
00E037  1               ; ============================================================================
00E037  1               ; $E037-$E08A
00E037  1               ; Evaluate global object state, select an active object, initialize its timer,
00E037  1               ; and wait for either input or timer expiration.
00E037  1               ;
00E037  1               ; Several conditions transfer directly to the next major path at $E08B.
00E037  1               ; ============================================================================
00E037  1               
00E037  1               ObjectStateDispatch:            ; $E037
00E037  1  A5 60            lda PendingStateTransition                 ; $E037: A5 60
00E039  1  D0 50            bne ObjectStateDispatch_NextPath
00E03B  1                                               ; $E039: D0 50
00E03B  1               
00E03B  1               ; ----------------------------------------------------------------------------
00E03B  1               ; Search or validate the current object state.
00E03B  1               ;
00E03B  1               ; Carry set from $E1CE skips the three setup helpers and continues at $E049.
00E03B  1               ; ----------------------------------------------------------------------------
00E03B  1               
00E03B  1  20 CE E1         jsr TestObjectGeometryFourTimes                   ; $E03B: 20 CE E1
00E03E  1  B0 09            bcs ObjectStateDispatch_CheckCandidate
00E040  1                                               ; $E03E: B0 09
00E040  1               
00E040  1               ; ----------------------------------------------------------------------------
00E040  1               ; Contract:
00E040  1               ;   Description: Internal dispatcher entry for the current object-state selection.
00E040  1               ;   Entry: Current object and selector state initialized.
00E040  1               ;   Returns/products: Dispatches selected state; products follow selected path.
00E040  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E040  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00E040  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E040  1               ;          comparison, load, or store path and are not a stable API product.
00E040  1               ;   Validation: Internal-entry contract; call sites: internal entry.
00E040  1               ; ----------------------------------------------------------------------------
00E040  1               ProcessObjectStateSelection:
00E040  1  20 47 E3         jsr ProcessCompactObjectState                   ; $E040: 20 47 E3
00E043  1  20 6A E3         jsr ProcessCompactObjectState_TestSelector                   ; $E043: 20 6A E3
00E046  1  20 31 E3         jsr FindAndQueueSelectedState                   ; $E046: 20 31 E3
00E049  1               
00E049  1               ; ----------------------------------------------------------------------------
00E049  1               ; Run the next selection test.
00E049  1               ;
00E049  1               ; Carry set transfers to the next major state path at $E08B.
00E049  1               ; ----------------------------------------------------------------------------
00E049  1               
00E049  1               ObjectStateDispatch_CheckCandidate: ; $E049
00E049  1  20 E7 E1         jsr FindEligibleObjectState                   ; $E049: 20 E7 E1
00E04C  1  B0 3D            bcs ObjectStateDispatch_NextPath
00E04E  1                                               ; $E04C: B0 3D
00E04E  1               
00E04E  1               ; ----------------------------------------------------------------------------
00E04E  1               ; When ObjectTransitionState is nonzero, validate the object-state selector.
00E04E  1               ; ----------------------------------------------------------------------------
00E04E  1               
00E04E  1  A5 6E            lda ObjectTransitionState                 ; $E04E: A5 6E
00E050  1  F0 0D            beq ObjectStateDispatch_InitializeObject
00E052  1                                               ; $E050: F0 0D
00E052  1               
00E052  1  A6 C3            ldx $C3                     ; $E052: A6 C3
00E054  1               
00E054  1  BD 98 05         lda $0598,x                 ; $E054: BD 98 05
00E057  1  4A               lsr                         ; $E057: 4A
00E058  1  A8               tay                         ; $E058: A8
00E059  1  C8               iny                         ; $E059: C8
00E05A  1               
00E05A  1  20 46 E2         jsr FindObjectStateForSelector                   ; $E05A: 20 46 E2
00E05D  1  30 2C            bmi ObjectStateDispatch_NextPath
00E05F  1                                               ; $E05D: 30 2C
00E05F  1               
00E05F  1               ; ----------------------------------------------------------------------------
00E05F  1               ; Initialize the selected object's compact state.
00E05F  1               ;
00E05F  1               ; GetCurrentObjectStateIndex derives X from CurrentObjectIndex. The entry indexed by $C3 is
00E05F  1               ; complemented and stored in $0595,X.
00E05F  1               ; ----------------------------------------------------------------------------
00E05F  1               
00E05F  1               ObjectStateDispatch_InitializeObject: ; $E05F
00E05F  1  20 68 DA         jsr GetCurrentObjectStateIndex
00E062  1                                               ; $E05F: 20 68 DA
00E062  1               
00E062  1  A5 C3            lda $C3                     ; $E062: A5 C3
00E064  1  49 FF            eor #$FF                    ; $E064: 49 FF
00E066  1  9D 95 05         sta $0595,x                 ; $E066: 9D 95 05
00E069  1               
00E069  1  A9 00            lda #$00                    ; $E069: A9 00
00E06B  1  85 9E            sta $9E                     ; $E06B: 85 9E
00E06D  1               
00E06D  1               ; ----------------------------------------------------------------------------
00E06D  1               ; Initialize the current object's timer to one.
00E06D  1               ;
00E06D  1               ; This is also the restart point after $E222 returns a nonzero result.
00E06D  1               ; ----------------------------------------------------------------------------
00E06D  1               
00E06D  1               ObjectStateDispatch_SetTimer:   ; $E06D
00E06D  1  A9 01            lda #$01                    ; $E06D: A9 01
00E06F  1               
00E06F  1               ObjectStateDispatch_StoreTimer: ; $E06F
00E06F  1  A6 E1            ldx CurrentObjectIndex      ; $E06F: A6 E1
00E071  1  9D B1 05         sta $05B1,x                 ; $E071: 9D B1 05
00E074  1               
00E074  1               ; ----------------------------------------------------------------------------
00E074  1               ; Wait for a frame and monitor the high two bits of InputAux2.
00E074  1               ; ----------------------------------------------------------------------------
00E074  1               
00E074  1               ObjectStateDispatch_TimerLoop:  ; $E074
00E074  1  20 48 EB         jsr SelectObjectEventBank1                   ; $E074: 20 48 EB
00E077  1               
00E077  1  A5 18            lda InputAux2               ; $E077: A5 18
00E079  1  29 C0            and #$C0                    ; $E079: 29 C0
00E07B  1  D0 0C            bne ObjectStateDispatch_InputActive
00E07D  1                                               ; $E07B: D0 0C
00E07D  1               
00E07D  1               ; ----------------------------------------------------------------------------
00E07D  1               ; No relevant input. Count the current object's timer down.
00E07D  1               ; ----------------------------------------------------------------------------
00E07D  1               
00E07D  1  A6 E1            ldx CurrentObjectIndex      ; $E07D: A6 E1
00E07F  1               
00E07F  1  DE B1 05         dec $05B1,x                 ; $E07F: DE B1 05
00E082  1  D0 F0            bne ObjectStateDispatch_TimerLoop
00E084  1                                               ; $E082: D0 F0
00E084  1               
00E084  1               ; ----------------------------------------------------------------------------
00E084  1               ; The timer expired. Run $E222.
00E084  1               ;
00E084  1               ; A nonzero result restarts the timer using the value currently in A.
00E084  1               ; A zero result falls through to $E089, but BNE is not taken there either,
00E084  1               ; allowing execution to continue at the next path at $E08B.
00E084  1               ; ----------------------------------------------------------------------------
00E084  1               
00E084  1  20 22 E2         jsr ProcessSelectedObjectState                   ; $E084: 20 22 E2
00E087  1  D0 E6            bne ObjectStateDispatch_StoreTimer
00E089  1                                               ; $E087: D0 E6
00E089  1               
00E089  1               ObjectStateDispatch_InputActive: ; $E089
00E089  1  D0 7C            bne ObjectStateDispatch_ForwardPath
00E08B  1                                               ; $E089: D0 7C
00E08B  1                                               ; When reached from $E07B, branches to $E107.
00E08B  1                                               ; When reached after zero from $E222, falls
00E08B  1                                               ; through to $E08B.
00E08B  1               
00E08B  1               ; ============================================================================
00E08B  1               ; $E08B-$E106
00E08B  1               ; Scan active object-state entries, evaluate their position and state tables,
00E08B  1               ; then wait for the next eligible input or state transition.
00E08B  1               ; ============================================================================
00E08B  1               
00E08B  1               ObjectStateDispatch_NextPath:   ; $E08B
00E08B  1  A6 E1            ldx CurrentObjectIndex      ; $E08B: A6 E1
00E08D  1               
00E08D  1  E0 04            cpx #$04                    ; $E08D: E0 04
00E08F  1  D0 65            bne ObjectStateDispatch_WaitLoop
00E091  1                                               ; $E08F: D0 65
00E091  1               
00E091  1               ; ----------------------------------------------------------------------------
00E091  1               ; Special setup for object offset $04.
00E091  1               ; ----------------------------------------------------------------------------
00E091  1               
00E091  1  A9 12            lda #$12                    ; $E091: A9 12
00E093  1  8D B2 03         sta $03B2                   ; $E093: 8D B2 03
00E096  1               
00E096  1  D0 5E            bne ObjectStateDispatch_WaitLoop
00E098  1                                               ; $E096: D0 5E
00E098  1                                               ; Always taken because A is nonzero.
00E098  1               
00E098  1               ; ============================================================================
00E098  1               ; $E098
00E098  1               ; Select the initial object-state table index.
00E098  1               ; ============================================================================
00E098  1               
00E098  1               ObjectStateDispatch_SelectStart: ; $E098
00E098  1  A2 02            ldx #$02                    ; $E098: A2 02
00E09A  1               
00E09A  1  E4 64            cpx SecondarySequenceState                 ; $E09A: E4 64
00E09C  1  D0 07            bne ObjectStateDispatch_AdvanceIndex
00E09E  1                                               ; $E09C: D0 07
00E09E  1               
00E09E  1  A5 BC            lda $BC                     ; $E09E: A5 BC
00E0A0  1  D0 03            bne ObjectStateDispatch_AdvanceIndex
00E0A2  1                                               ; $E0A0: D0 03
00E0A2  1               
00E0A2  1               ; ----------------------------------------------------------------------------
00E0A2  1               ; When SecondarySequenceState equals two and $BC is zero, use $BC as the initial index and
00E0A2  1               ; increment it for the next pass.
00E0A2  1               ; ----------------------------------------------------------------------------
00E0A2  1               
00E0A2  1  AA               tax                         ; $E0A2: AA
00E0A3  1                                               ; A is zero, so X becomes zero.
00E0A3  1               
00E0A3  1  E6 BC            inc $BC                     ; $E0A3: E6 BC
00E0A5  1               
00E0A5  1               ObjectStateDispatch_AdvanceIndex: ; $E0A5
00E0A5  1  E8               inx                         ; $E0A5: E8
00E0A6  1  86 C3            stx $C3                     ; $E0A6: 86 C3
00E0A8  1               
00E0A8  1               ; ============================================================================
00E0A8  1               ; $E0A8
00E0A8  1               ; Search object-state entries beginning at index $C3.
00E0A8  1               ; ============================================================================
00E0A8  1               
00E0A8  1               ObjectStateDispatch_Search:     ; $E0A8
00E0A8  1  A6 C3            ldx $C3                     ; $E0A8: A6 C3
00E0AA  1               
00E0AA  1  BD 98 05         lda $0598,x                 ; $E0AA: BD 98 05
00E0AD  1  30 43            bmi ObjectStateDispatch_NextEntry
00E0AF  1                                               ; $E0AD: 30 43
00E0AF  1               
00E0AF  1               ; ----------------------------------------------------------------------------
00E0AF  1               ; Load the corresponding compact state from zero-page $95-$98.
00E0AF  1               ; ----------------------------------------------------------------------------
00E0AF  1               
00E0AF  1  B4 95            ldy $95,x                   ; $E0AF: B4 95
00E0B1  1  D0 04            bne ObjectStateDispatch_TestState
00E0B3  1                                               ; $E0B1: D0 04
00E0B3  1               
00E0B3  1               ; ----------------------------------------------------------------------------
00E0B3  1               ; A zero compact state derives a value from the table index.
00E0B3  1               ;
00E0B3  1               ; A nonzero doubled X branches to the forward transition at
00E0B3  1               ; ObjectStateDispatch_ForwardTransition
00E0B3  1               ; ----------------------------------------------------------------------------
00E0B3  1               
00E0B3  1  8A               txa                         ; $E0B3: 8A
00E0B4  1  0A               asl                         ; $E0B4: 0A
00E0B5  1  D0 5D            bne ObjectStateDispatch_ForwardTransition
00E0B7  1                                               ; $E0B5: D0 5D
00E0B7  1               
00E0B7  1               ; ----------------------------------------------------------------------------
00E0B7  1               ; Shift the compact state and reject entries whose low bit was clear.
00E0B7  1               ; ----------------------------------------------------------------------------
00E0B7  1               
00E0B7  1               ObjectStateDispatch_TestState:  ; $E0B7
00E0B7  1  4A               lsr                         ; $E0B7: 4A
00E0B8  1  90 38            bcc ObjectStateDispatch_NextEntry
00E0BA  1                                               ; $E0B8: 90 38
00E0BA  1               
00E0BA  1  85 C2            sta $C2                     ; $E0BA: 85 C2
00E0BC  1  A8               tay                         ; $E0BC: A8
00E0BD  1  C8               iny                         ; $E0BD: C8
00E0BE  1               
00E0BE  1               ; ----------------------------------------------------------------------------
00E0BE  1               ; Test the selected state using the helper at $E246.
00E0BE  1               ; ----------------------------------------------------------------------------
00E0BE  1               
00E0BE  1  20 46 E2         jsr FindObjectStateForSelector                   ; $E0BE: 20 46 E2
00E0C1  1  10 09            bpl ObjectStateDispatch_CompareTables
00E0C3  1                                               ; $E0C1: 10 09
00E0C3  1               
00E0C3  1               ; ----------------------------------------------------------------------------
00E0C3  1               ; A negative result is ignored while ObjectTransitionState is nonzero.
00E0C3  1               ;
00E0C3  1               ; Otherwise, increment A and transfer to the forward transition at
00E0C3  1               ; ObjectStateDispatch_ForwardTransition
00E0C3  1               ; ----------------------------------------------------------------------------
00E0C3  1               
00E0C3  1  A4 6E            ldy ObjectTransitionState                 ; $E0C3: A4 6E
00E0C5  1  D0 2B            bne ObjectStateDispatch_NextEntry
00E0C7  1                                               ; $E0C5: D0 2B
00E0C7  1               
00E0C7  1  18               clc                         ; $E0C7: 18
00E0C8  1  69 01            adc #$01                    ; $E0C8: 69 01
00E0CA  1  D0 48            bne ObjectStateDispatch_ForwardTransition
00E0CC  1                                               ; $E0CA: D0 48
00E0CC  1               
00E0CC  1               ; ============================================================================
00E0CC  1               ; $E0CC
00E0CC  1               ; Compare the selected object's high coordinate against overlapping lookup
00E0CC  1               ; tables at $E021, $E024, and $E027.
00E0CC  1               ; ============================================================================
00E0CC  1               
00E0CC  1               ObjectStateDispatch_CompareTables: ; $E0CC
00E0CC  1  A4 C2            ldy $C2                     ; $E0CC: A4 C2
00E0CE  1               
00E0CE  1  A5 C3            lda $C3                     ; $E0CE: A5 C3
00E0D0  1  0A               asl                         ; $E0D0: 0A
00E0D1  1  AA               tax                         ; $E0D1: AA
00E0D2  1               
00E0D2  1               ; ----------------------------------------------------------------------------
00E0D2  1               ; Signed/bitwise first comparison.
00E0D2  1               ; ----------------------------------------------------------------------------
00E0D2  1               
00E0D2  1  BD 10 05         lda $0510,x                 ; $E0D2: BD 10 05
00E0D5  1               
00E0D5  1  F9 24 E0         sbc $E024,y                 ; $E0D5: F9 24 E0
00E0D8  1  59 27 E0         eor $E027,y                 ; $E0D8: 59 27 E0
00E0DB  1               
00E0DB  1  10 15            bpl ObjectStateDispatch_NextEntry
00E0DD  1                                               ; $E0DB: 10 15
00E0DD  1               
00E0DD  1               ; ----------------------------------------------------------------------------
00E0DD  1               ; Second comparison against the table beginning at $E021.
00E0DD  1               ;
00E0DD  1               ; ROL incorporates the comparison carry into Y.
00E0DD  1               ; ----------------------------------------------------------------------------
00E0DD  1               
00E0DD  1  BD 10 05         lda $0510,x                 ; $E0DD: BD 10 05
00E0E0  1  D9 21 E0         cmp $E021,y                 ; $E0E0: D9 21 E0
00E0E3  1               
00E0E3  1  98               tya                         ; $E0E3: 98
00E0E4  1  2A               rol                         ; $E0E4: 2A
00E0E5  1  A8               tay                         ; $E0E5: A8
00E0E6  1               
00E0E6  1               ; ----------------------------------------------------------------------------
00E0E6  1               ; Combine the indexed activity byte at $0573,X with the comparison result.
00E0E6  1               ; ----------------------------------------------------------------------------
00E0E6  1               
00E0E6  1  BD 73 05         lda $0573,x                 ; $E0E6: BD 73 05
00E0E9  1  0A               asl                         ; $E0E9: 0A
00E0EA  1               
00E0EA  1  98               tya                         ; $E0EA: 98
00E0EB  1  2A               rol                         ; $E0EB: 2A
00E0EC  1  A8               tay                         ; $E0EC: A8
00E0ED  1               
00E0ED  1  B9 27 E0         lda $E027,y                 ; $E0ED: B9 27 E0
00E0F0  1  D0 22            bne ObjectStateDispatch_ForwardTransition
00E0F2  1                                               ; $E0F0: D0 22
00E0F2  1               
00E0F2  1               ; ----------------------------------------------------------------------------
00E0F2  1               ; Reject this entry and continue searching backward.
00E0F2  1               ; ----------------------------------------------------------------------------
00E0F2  1               
00E0F2  1               ObjectStateDispatch_NextEntry:  ; $E0F2
00E0F2  1  C6 C3            dec $C3                     ; $E0F2: C6 C3
00E0F4  1  10 B2            bpl ObjectStateDispatch_Search
00E0F6  1                                               ; $E0F4: 10 B2
00E0F6  1               
00E0F6  1               ; ============================================================================
00E0F6  1               ; $E0F6
00E0F6  1               ; Wait until the global state and input conditions permit another scan.
00E0F6  1               ; ============================================================================
00E0F6  1               
00E0F6  1               ObjectStateDispatch_WaitLoop:   ; $E0F6
00E0F6  1  20 48 EB         jsr SelectObjectEventBank1                   ; $E0F6: 20 48 EB
00E0F9  1               
00E0F9  1  A5 60            lda PendingStateTransition                 ; $E0F9: A5 60
00E0FB  1  D0 F9            bne ObjectStateDispatch_WaitLoop
00E0FD  1                                               ; $E0FB: D0 F9
00E0FD  1               
00E0FD  1               ; ----------------------------------------------------------------------------
00E0FD  1               ; If $10 is zero, restart object-state selection at $E098.
00E0FD  1               ; ----------------------------------------------------------------------------
00E0FD  1               
00E0FD  1  A5 10            lda $10                     ; $E0FD: A5 10
00E0FF  1  F0 97            beq ObjectStateDispatch_SelectStart
00E101  1                                               ; $E0FF: F0 97
00E101  1               
00E101  1               ; ----------------------------------------------------------------------------
00E101  1               ; Otherwise, wait until either of the high two bits in InputAux2 becomes set.
00E101  1               ; ----------------------------------------------------------------------------
00E101  1               
00E101  1  A5 18            lda InputAux2               ; $E101: A5 18
00E103  1  29 C0            and #$C0                    ; $E103: 29 C0
00E105  1  F0 EF            beq ObjectStateDispatch_WaitLoop
00E107  1                                               ; $E105: F0 EF
00E107  1               
00E107  1               
00E107  1               ; ============================================================================
00E107  1               ; $E107-$E16B
00E107  1               ; Convert input state into an object-state selection, process event slot $1D,
00E107  1               ; assign the selected state to an object, and either retry geometry processing
00E107  1               ; or return to the main object-state dispatch loop.
00E107  1               ; ============================================================================
00E107  1               
00E107  1               ObjectStateDispatch_ForwardPath: ; $E107
00E107  1  A2 FF            ldx #$FF                    ; $E107: A2 FF
00E109  1               
00E109  1               ; ----------------------------------------------------------------------------
00E109  1               ; Derive a compact index from InputState2.
00E109  1               ;
00E109  1               ; InputState2 is ORed with $F0, then shifted right until a zero bit reaches
00E109  1               ; carry. X begins at $FF and is incremented before each shift.
00E109  1               ; ----------------------------------------------------------------------------
00E109  1               
00E109  1  A5 14            lda InputState2             ; $E109: A5 14
00E10B  1  09 F0            ora #$F0                    ; $E10B: 09 F0
00E10D  1               
00E10D  1               ObjectStateDispatch_FindInputIndex: ; $E10D
00E10D  1  E8               inx                         ; $E10D: E8
00E10E  1  4A               lsr                         ; $E10E: 4A
00E10F  1  90 FC            bcc ObjectStateDispatch_FindInputIndex
00E111  1                                               ; $E10F: 90 FC
00E111  1               
00E111  1               ; ----------------------------------------------------------------------------
00E111  1               ; Use the resulting X index to select a byte from the lookup data beginning at
00E111  1               ; $E01D.
00E111  1               ; ----------------------------------------------------------------------------
00E111  1               
00E111  1  BD 1D E0         lda $E01D,x                 ; $E111: BD 1D E0
00E114  1               ObjectStateDispatch_ForwardTransition:
00E114  1  48               pha                         ; $E114: 48
00E115  1               
00E115  1               ; ----------------------------------------------------------------------------
00E115  1               ; Process event slot $1D and run two engine helpers.
00E115  1               ; ----------------------------------------------------------------------------
00E115  1               
00E115  1  A0 1D            ldy #$1D                    ; $E115: A0 1D
00E117  1  20 66 EB         jsr DispatchNextQueuedEvent                   ; $E117: 20 66 EB
00E11A  1               
00E11A  1  20 D3 E2         jsr ClearCurrentObjectMovement                   ; $E11A: 20 D3 E2
00E11D  1  20 E6 E3         jsr InitializeBaseObjectFromCurrent                   ; $E11D: 20 E6 E3
00E120  1               
00E120  1               ; ----------------------------------------------------------------------------
00E120  1               ; Restore the selected lookup value and divide it by two.
00E120  1               ; Store the resulting compact state in $C2.
00E120  1               ; ----------------------------------------------------------------------------
00E120  1               
00E120  1  68               pla                         ; $E120: 68
00E121  1  4A               lsr                         ; $E121: 4A
00E122  1  85 C2            sta $C2                     ; $E122: 85 C2
00E124  1               
00E124  1               ; ----------------------------------------------------------------------------
00E124  1               ; Obtain the current object/event selector.
00E124  1               ; ----------------------------------------------------------------------------
00E124  1               
00E124  1  20 DC E3         jsr GetCurrentObjectSelectorAndState                   ; $E124: 20 DC E3
00E127  1               
00E127  1  A5 C2            lda $C2                     ; $E127: A5 C2
00E129  1               
00E129  1               ; ----------------------------------------------------------------------------
00E129  1               ; Adjust $BB for two special selector/state combinations:
00E129  1               ;
00E129  1               ;   Y = $02 and A = $04  -> $BB = $01
00E129  1               ;   Y = $04 and A = $02  -> $BB = $03
00E129  1               ; ----------------------------------------------------------------------------
00E129  1               
00E129  1  C0 02            cpy #$02                    ; $E129: C0 02
00E12B  1  D0 08            bne ObjectStateDispatch_CheckSelector4
00E12D  1                                               ; $E12B: D0 08
00E12D  1               
00E12D  1  C9 04            cmp #$04                    ; $E12D: C9 04
00E12F  1  D0 04            bne ObjectStateDispatch_CheckSelector4
00E131  1                                               ; $E12F: D0 04
00E131  1               
00E131  1  A2 01            ldx #$01                    ; $E131: A2 01
00E133  1  86 BB            stx $BB                     ; $E133: 86 BB
00E135  1               
00E135  1               ObjectStateDispatch_CheckSelector4: ; $E135
00E135  1  C0 04            cpy #$04                    ; $E135: C0 04
00E137  1  D0 08            bne ObjectStateDispatch_AssignState
00E139  1                                               ; $E137: D0 08
00E139  1               
00E139  1  C9 02            cmp #$02                    ; $E139: C9 02
00E13B  1  D0 04            bne ObjectStateDispatch_AssignState
00E13D  1                                               ; $E13B: D0 04
00E13D  1               
00E13D  1  A2 03            ldx #$03                    ; $E13D: A2 03
00E13F  1  86 BB            stx $BB                     ; $E13F: 86 BB
00E141  1               
00E141  1               ; ----------------------------------------------------------------------------
00E141  1               ; Select the target object through $E25E.
00E141  1               ;
00E141  1               ; The helper returns an object offset in Y.
00E141  1               ; ----------------------------------------------------------------------------
00E141  1               
00E141  1               ObjectStateDispatch_AssignState: ; $E141
00E141  1  20 5E E2         jsr FindNearestCandidateObject                   ; $E141: 20 5E E2
00E144  1               
00E144  1               ; ----------------------------------------------------------------------------
00E144  1               ; Convert the object offset in Y into a compact object-state index and store
00E144  1               ; the selected state from $C2 into $0595,X.
00E144  1               ; ----------------------------------------------------------------------------
00E144  1               
00E144  1  98               tya                         ; $E144: 98
00E145  1  4A               lsr                         ; $E145: 4A
00E146  1  AA               tax                         ; $E146: AA
00E147  1               
00E147  1  A5 C2            lda $C2                     ; $E147: A5 C2
00E149  1  9D 95 05         sta $0595,x                 ; $E149: 9D 95 05
00E14C  1               
00E14C  1               ; ----------------------------------------------------------------------------
00E14C  1               ; Compare the selected object offset in Y against CurrentObjectIndex.
00E14C  1               ;
00E14C  1               ; If they differ, continue at the next path at $E16C.
00E14C  1               ; ----------------------------------------------------------------------------
00E14C  1               
00E14C  1  C4 E1            cpy CurrentObjectIndex      ; $E14C: C4 E1
00E14E  1  D0 1C            bne ObjectStateDispatch_DifferentObject
00E150  1                                               ; $E14E: D0 1C
00E150  1               
00E150  1               ; ----------------------------------------------------------------------------
00E150  1               ; The selected object is the current object.
00E150  1               ;
00E150  1               ; Prepare and test its geometry. Carry set runs $E313 and retries the test.
00E150  1               ; ----------------------------------------------------------------------------
00E150  1               
00E150  1               ObjectStateDispatch_TestSelectedObject: ; $E150
00E150  1  20 74 E4         jsr SelectGeometryRecord_Default                   ; $E150: 20 74 E4
00E153  1  20 5F E5         jsr ApplyCurrentObjectGeometry                   ; $E153: 20 5F E5
00E156  1               
00E156  1  90 06            bcc ObjectStateDispatch_SelectedObjectClear
00E158  1                                               ; $E156: 90 06
00E158  1               
00E158  1  20 13 E3         jsr UpdateCurrentObjectAnimationAndWait                   ; $E158: 20 13 E3
00E15B  1  4C 50 E1         jmp ObjectStateDispatch_TestSelectedObject
00E15E  1                                               ; $E15B: 4C 50 E1
00E15E  1               
00E15E  1               ; ----------------------------------------------------------------------------
00E15E  1               ; Geometry cleared.
00E15E  1               ;
00E15E  1               ; Update the current object's display state, derive its selector, save that
00E15E  1               ; selector in $9E, run the engine helper, and return to the setup path at
00E15E  1               ; $E040.
00E15E  1               ; ----------------------------------------------------------------------------
00E15E  1               
00E15E  1               ObjectStateDispatch_SelectedObjectClear: ; $E15E
00E15E  1  20 D4 DF         jsr UpdateCurrentObjectDisplayState
00E161  1                                               ; $E15E: 20 D4 DF
00E161  1               
00E161  1  20 DC E3         jsr GetCurrentObjectSelectorAndState                   ; $E161: 20 DC E3
00E164  1  84 9E            sty $9E                     ; $E164: 84 9E
00E166  1               
00E166  1  20 E6 E3         jsr InitializeBaseObjectFromCurrent                   ; $E166: 20 E6 E3
00E169  1               
00E169  1  4C 40 E0         jmp ProcessObjectStateSelection                   ; $E169: 4C 40 E0
00E16C  1               
00E16C  1               ; ============================================================================
00E16C  1               ; $E16C-$E1CD
00E16C  1               ; Process the selected object's event, update its animation, wait, and leave
00E16C  1               ; through the common engine exit.
00E16C  1               ;
00E16C  1               ; Entry:
00E16C  1               ;   Y = selected object/event offset returned by $E25E
00E16C  1               ;   $C2 = selected compact state
00E16C  1               ; ============================================================================
00E16C  1               
00E16C  1               ObjectStateDispatch_DifferentObject: ; $E16C
00E16C  1  84 C4            sty $C4                     ; $E16C: 84 C4
00E16E  1               
00E16E  1               ; ----------------------------------------------------------------------------
00E16E  1               ; Process the selected object's event slot and wait ten ticks.
00E16E  1               ; ----------------------------------------------------------------------------
00E16E  1               
00E16E  1  20 66 EB         jsr DispatchNextQueuedEvent                   ; $E16E: 20 66 EB
00E171  1               
00E171  1  A9 0A            lda #$0A                    ; $E171: A9 0A
00E173  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $E173: 20 41 EB
00E176  1               
00E176  1               ; ----------------------------------------------------------------------------
00E176  1               ; Dispatch the selected object through $E29B.
00E176  1               ;
00E176  1               ; X is restored from $C4. The inline record contains a leading zero byte and
00E176  1               ; stored address $E3AB. The exact dispatch convention will be confirmed when
00E176  1               ; $E29B and $E3AB are decoded.
00E176  1               ; ----------------------------------------------------------------------------
00E176  1               
00E176  1  A6 C4            ldx $C4                     ; $E176: A6 C4
00E178  1  20 9B E2         jsr DispatchInlineObjectCommand                   ; $E178: 20 9B E2
00E17B  1               
00E17B  1  00 AB E3         .byte $00,$AB,$E3           ; $E17B-$E17D
00E17E  1               
00E17E  1               ; ----------------------------------------------------------------------------
00E17E  1               ; Run the shared engine update, then clear $9E.
00E17E  1               ; ----------------------------------------------------------------------------
00E17E  1               
00E17E  1  20 E6 E3         jsr InitializeBaseObjectFromCurrent                   ; $E17E: 20 E6 E3
00E181  1               
00E181  1  A9 00            lda #$00                    ; $E181: A9 00
00E183  1  85 9E            sta $9E                     ; $E183: 85 9E
00E185  1               
00E185  1               ; ----------------------------------------------------------------------------
00E185  1               ; Object offset $04 uses a short alternate exit at $E1C6.
00E185  1               ; ----------------------------------------------------------------------------
00E185  1               
00E185  1  A6 E1            ldx CurrentObjectIndex      ; $E185: A6 E1
00E187  1  E0 04            cpx #$04                    ; $E187: E0 04
00E189  1  F0 3B            beq ObjectStateDispatch_Object04
00E18B  1                                               ; $E189: F0 3B
00E18B  1               
00E18B  1               ; ----------------------------------------------------------------------------
00E18B  1               ; Select an animation attribute according to $C2 and the sign of the current
00E18B  1               ; object's high horizontal coordinate.
00E18B  1               ;
00E18B  1               ; The table access intentionally uses base $DFCD.
00E18B  1               ; ----------------------------------------------------------------------------
00E18B  1               
00E18B  1  A6 E1            ldx CurrentObjectIndex      ; $E18B: A6 E1
00E18D  1               
00E18D  1  A4 C2            ldy $C2                     ; $E18D: A4 C2
00E18F  1  B9 CD DF         lda $DFCD,y                 ; $E18F: B9 CD DF
00E192  1               
00E192  1  A0 3F            ldy #$3F                    ; $E192: A0 3F
00E194  1               
00E194  1  DD 0A 05         cmp $050A,x                 ; $E194: DD 0A 05
00E197  1  10 02            bpl ObjectStateDispatch_SaveFirstFrame
00E199  1                                               ; $E197: 10 02
00E199  1               
00E199  1  A0 40            ldy #$40                    ; $E199: A0 40
00E19B  1               
00E19B  1               ; ----------------------------------------------------------------------------
00E19B  1               ; Convert CurrentObjectIndex to the compact sprite-array index.
00E19B  1               ; ----------------------------------------------------------------------------
00E19B  1               
00E19B  1               ObjectStateDispatch_SaveFirstFrame: ; $E19B
00E19B  1  A5 E1            lda CurrentObjectIndex      ; $E19B: A5 E1
00E19D  1  4A               lsr                         ; $E19D: 4A
00E19E  1  AA               tax                         ; $E19E: AA
00E19F  1               
00E19F  1               ; ----------------------------------------------------------------------------
00E19F  1               ; Compact indices below $0C receive the selected attribute $3F/$40.
00E19F  1               ; ----------------------------------------------------------------------------
00E19F  1               
00E19F  1  E0 0C            cpx #$0C                    ; $E19F: E0 0C
00E1A1  1  B0 04            bcs ObjectStateDispatch_SaveFrame5F
00E1A3  1                                               ; $E1A1: B0 04
00E1A3  1               
00E1A3  1  98               tya                         ; $E1A3: 98
00E1A4  1  9D B0 03         sta $03B0,x                 ; $E1A4: 9D B0 03
00E1A7  1               
00E1A7  1               ObjectStateDispatch_SaveFrame5F: ; $E1A7
00E1A7  1  A9 5F            lda #$5F                    ; $E1A7: A9 5F
00E1A9  1  9D 9B 03         sta $039B,x                 ; $E1A9: 9D 9B 03
00E1AC  1               
00E1AC  1               ; ----------------------------------------------------------------------------
00E1AC  1               ; Hold this animation for $3C ticks.
00E1AC  1               ; ----------------------------------------------------------------------------
00E1AC  1               
00E1AC  1  A9 3C            lda #$3C                    ; $E1AC: A9 3C
00E1AE  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $E1AE: 20 41 EB
00E1B1  1               
00E1B1  1               ; ----------------------------------------------------------------------------
00E1B1  1               ; Replace the animation with frame $67. Compact indices below $0C also receive
00E1B1  1               ; attribute $2F.
00E1B1  1               ; ----------------------------------------------------------------------------
00E1B1  1               
00E1B1  1  A5 E1            lda CurrentObjectIndex      ; $E1B1: A5 E1
00E1B3  1  4A               lsr                         ; $E1B3: 4A
00E1B4  1  AA               tax                         ; $E1B4: AA
00E1B5  1               
00E1B5  1  E0 0C            cpx #$0C                    ; $E1B5: E0 0C
00E1B7  1  B0 05            bcs ObjectStateDispatch_SaveFrame67
00E1B9  1                                               ; $E1B7: B0 05
00E1B9  1               
00E1B9  1  A9 2F            lda #$2F                    ; $E1B9: A9 2F
00E1BB  1  9D B0 03         sta $03B0,x                 ; $E1BB: 9D B0 03
00E1BE  1               
00E1BE  1               ObjectStateDispatch_SaveFrame67: ; $E1BE
00E1BE  1  A9 67            lda #$67                    ; $E1BE: A9 67
00E1C0  1  9D 9B 03         sta $039B,x                 ; $E1C0: 9D 9B 03
00E1C3  1               
00E1C3  1  4C 6A EB         jmp CommonEngineExit                   ; $E1C3: 4C 6A EB
00E1C6  1               
00E1C6  1               ; ----------------------------------------------------------------------------
00E1C6  1               ; Special exit for object offset $04.
00E1C6  1               ; ----------------------------------------------------------------------------
00E1C6  1               
00E1C6  1               ObjectStateDispatch_Object04:   ; $E1C6
00E1C6  1  A9 13            lda #$13                    ; $E1C6: A9 13
00E1C8  1  8D B2 03         sta $03B2                   ; $E1C8: 8D B2 03
00E1CB  1               
00E1CB  1  4C 6A EB         jmp CommonEngineExit                   ; $E1CB: 4C 6A EB
00E1CE  1               
00E1CE  1               ; ============================================================================
00E1CE  1               ; $E1CE-$E1E6
00E1CE  1               ; Repeat the geometry test while its result is at least two.
00E1CE  1               ;
00E1CE  1               ; The loop permits up to four geometry-test attempts.
00E1CE  1               ;
00E1CE  1               ; Return:
00E1CE  1               ;   A < $02, or the four-attempt counter expired.
00E1CE  1               ; ============================================================================
00E1CE  1               
00E1CE  1               ; ----------------------------------------------------------------------------
00E1CE  1               ; Contract:
00E1CE  1               ;   Description: Implements Test Object Geometry Four Times.
00E1CE  1               ;   Entry: Registers: A, Y
00E1CE  1               ;   Returns/products: Registers/clobbers: Y
00E1CE  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E1CE  1               ;   Memory effects: $c2
00E1CE  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E1CE  1               ;          comparison, load, or store path and are not a stable API product.
00E1CE  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00E1CE  1               ; ----------------------------------------------------------------------------
00E1CE  1               TestObjectGeometryFourTimes:    ; $E1CE
00E1CE  1  A0 04            ldy #$04                    ; $E1CE: A0 04
00E1D0  1  84 C2            sty $C2                     ; $E1D0: 84 C2
00E1D2  1               
00E1D2  1               TestObjectGeometryFourTimes_Loop: ; $E1D2
00E1D2  1  20 74 E4         jsr SelectGeometryRecord_Default                   ; $E1D2: 20 74 E4
00E1D5  1  20 C2 E4         jsr LoadGeometryRecord                   ; $E1D5: 20 C2 E4
00E1D8  1  20 DB E4         jsr CalculateCurrentGeometryDifference                   ; $E1D8: 20 DB E4
00E1DB  1  20 02 E5         jsr EvaluateGeometryDifference                   ; $E1DB: 20 02 E5
00E1DE  1               
00E1DE  1  C9 02            cmp #$02                    ; $E1DE: C9 02
00E1E0  1  90 04            bcc TestObjectGeometryFourTimes_Return
00E1E2  1                                               ; $E1E0: 90 04
00E1E2  1               
00E1E2  1  C6 C2            dec $C2                     ; $E1E2: C6 C2
00E1E4  1  D0 EC            bne TestObjectGeometryFourTimes_Loop
00E1E6  1                                               ; $E1E4: D0 EC
00E1E6  1               
00E1E6  1               TestObjectGeometryFourTimes_Return: ; $E1E6
00E1E6  1  60               rts                         ; $E1E6: 60
00E1E7  1               
00E1E7  1               ; ============================================================================
00E1E7  1               ; $E1E7-$E200
00E1E7  1               ; Search object-state entries $0598-$059B for an eligible geometry result.
00E1E7  1               ;
00E1E7  1               ; The routine scans indices three through zero. An entry is eligible when:
00E1E7  1               ;
00E1E7  1               ;   1. Its state byte is nonnegative.
00E1E7  1               ;   2. Bit zero of the state byte is set.
00E1E7  1               ;   3. Its geometry-test result is at least $0C.
00E1E7  1               ;
00E1E7  1               ; Return:
00E1E7  1               ;   C = clear when a qualifying entry is found
00E1E7  1               ;   C = set when no entry qualifies
00E1E7  1               ;
00E1E7  1               ;   $C3 = qualifying index, or $FF after the search is exhausted
00E1E7  1               ; ============================================================================
00E1E7  1               
00E1E7  1               ; ----------------------------------------------------------------------------
00E1E7  1               ; Contract:
00E1E7  1               ;   Description: Implements Find Eligible Object State.
00E1E7  1               ;   Entry: Registers: A, Y; Memory: $0598, $c3
00E1E7  1               ;   Returns/products: Registers/clobbers: A, Y
00E1E7  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E1E7  1               ;   Memory effects: $c3
00E1E7  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E1E7  1               ;          comparison, load, or store path and are not a stable API product.
00E1E7  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00E1E7  1               ; ----------------------------------------------------------------------------
00E1E7  1               FindEligibleObjectState:        ; $E1E7
00E1E7  1  A0 03            ldy #$03                    ; $E1E7: A0 03
00E1E9  1               
00E1E9  1               ; ----------------------------------------------------------------------------
00E1E9  1               ; Save the current table index.
00E1E9  1               ; ----------------------------------------------------------------------------
00E1E9  1               
00E1E9  1               FindEligibleObjectState_Loop:   ; $E1E9
00E1E9  1  84 C3            sty $C3                     ; $E1E9: 84 C3
00E1EB  1               
00E1EB  1               ; ----------------------------------------------------------------------------
00E1EB  1               ; Reject inactive entries whose state byte is negative.
00E1EB  1               ; ----------------------------------------------------------------------------
00E1EB  1               
00E1EB  1  B9 98 05         lda $0598,y                 ; $E1EB: B9 98 05
00E1EE  1  30 0A            bmi FindEligibleObjectState_Next
00E1F0  1                                               ; $E1EE: 30 0A
00E1F0  1               
00E1F0  1               ; ----------------------------------------------------------------------------
00E1F0  1               ; Shift the state byte and reject entries whose low bit was clear.
00E1F0  1               ; ----------------------------------------------------------------------------
00E1F0  1               
00E1F0  1  4A               lsr                         ; $E1F0: 4A
00E1F1  1  90 07            bcc FindEligibleObjectState_Next
00E1F3  1                                               ; $E1F1: 90 07
00E1F3  1               
00E1F3  1               ; ----------------------------------------------------------------------------
00E1F3  1               ; Test the geometry associated with the current state-table index.
00E1F3  1               ;
00E1F3  1               ; Results below $0C qualify and return immediately with carry clear from
00E1F3  1               ; CMP #$0C. Results at least $0C continue searching.
00E1F3  1               ; ----------------------------------------------------------------------------
00E1F3  1               
00E1F3  1  20 01 E2         jsr TestIndexedObjectGeometry
00E1F6  1                                               ; $E1F3: 20 01 E2
00E1F6  1               
00E1F6  1  C9 0C            cmp #$0C                    ; $E1F6: C9 0C
00E1F8  1  90 06            bcc FindEligibleObjectState_Return
00E1FA  1                                               ; $E1F8: 90 06
00E1FA  1               
00E1FA  1               ; ----------------------------------------------------------------------------
00E1FA  1               ; Continue with the preceding state-table index.
00E1FA  1               ; ----------------------------------------------------------------------------
00E1FA  1               
00E1FA  1               FindEligibleObjectState_Next:   ; $E1FA
00E1FA  1  A4 C3            ldy $C3                     ; $E1FA: A4 C3
00E1FC  1  88               dey                         ; $E1FC: 88
00E1FD  1  10 EA            bpl FindEligibleObjectState_Loop
00E1FF  1                                               ; $E1FD: 10 EA
00E1FF  1               
00E1FF  1               ; ----------------------------------------------------------------------------
00E1FF  1               ; No entry qualified. Return carry set.
00E1FF  1               ; ----------------------------------------------------------------------------
00E1FF  1               
00E1FF  1  38               sec                         ; $E1FF: 38
00E200  1               
00E200  1               FindEligibleObjectState_Return: ; $E200
00E200  1  60               rts                         ; $E200: 60
00E201  1               
00E201  1               ; ============================================================================
00E201  1               ; $E201-$E221
00E201  1               ; Copy coordinates for the state-table entry selected in $C3 into the geometry
00E201  1               ; arguments, process them, and test the resulting region.
00E201  1               ;
00E201  1               ; Entry:
00E201  1               ;   $C3 = compact object/state index
00E201  1               ;
00E201  1               ; Return:
00E201  1               ;   A = result returned by $E502
00E201  1               ;   Flags from CMP #$03
00E201  1               ; ============================================================================
00E201  1               
00E201  1               TestIndexedObjectGeometry:      ; $E201
00E201  1  A5 C3            lda $C3                     ; $E201: A5 C3
00E203  1  0A               asl                         ; $E203: 0A
00E204  1  A8               tay                         ; $E204: A8
00E205  1                                               ; Convert compact index to object-array offset.
00E205  1               
00E205  1               ; ----------------------------------------------------------------------------
00E205  1               ; Copy the selected object's horizontal coordinate.
00E205  1               ; ----------------------------------------------------------------------------
00E205  1               
00E205  1  B9 0F 05         lda $050F,y                 ; $E205: B9 0F 05
00E208  1  85 B2            sta $B2                     ; $E208: 85 B2
00E20A  1               
00E20A  1  B9 10 05         lda $0510,y                 ; $E20A: B9 10 05
00E20D  1  85 B3            sta $B3                     ; $E20D: 85 B3
00E20F  1               
00E20F  1               ; ----------------------------------------------------------------------------
00E20F  1               ; Copy the selected object's vertical coordinate.
00E20F  1               ; ----------------------------------------------------------------------------
00E20F  1               
00E20F  1  B9 40 05         lda $0540,y                 ; $E20F: B9 40 05
00E212  1  85 B4            sta $B4                     ; $E212: 85 B4
00E214  1               
00E214  1  B9 41 05         lda $0541,y                 ; $E214: B9 41 05
00E217  1  85 B5            sta $B5                     ; $E217: 85 B5
00E219  1               
00E219  1               ; ----------------------------------------------------------------------------
00E219  1               ; Process the coordinates and perform the final geometry test.
00E219  1               ; ----------------------------------------------------------------------------
00E219  1               
00E219  1  20 DB E4         jsr CalculateCurrentGeometryDifference                   ; $E219: 20 DB E4
00E21C  1  20 02 E5         jsr EvaluateGeometryDifference                   ; $E21C: 20 02 E5
00E21F  1               
00E21F  1  C9 03            cmp #$03                    ; $E21F: C9 03
00E221  1  60               rts                         ; $E221: 60
00E222  1               
00E222  1               ; ============================================================================
00E222  1               ; $E222-$E245
00E222  1               ; Derive an object-state index, test its geometry, and route according to the
00E222  1               ; result.
00E222  1               ;
00E222  1               ; Return behavior:
00E222  1               ;   This helper does not return directly. Both paths tail-jump elsewhere.
00E222  1               ; ============================================================================
00E222  1               
00E222  1               ; ----------------------------------------------------------------------------
00E222  1               ; Contract:
00E222  1               ;   Description: Processes Selected Object State.
00E222  1               ;   Entry: Registers: A, Y
00E222  1               ;   Returns/products: Registers/clobbers: A
00E222  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E222  1               ;   Memory effects: $c3
00E222  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E222  1               ;          comparison, load, or store path and are not a stable API product.
00E222  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00E222  1               ; ----------------------------------------------------------------------------
00E222  1               ProcessSelectedObjectState:     ; $E222
00E222  1  20 DC E3         jsr GetCurrentObjectSelectorAndState                   ; $E222: 20 DC E3
00E225  1               
00E225  1               ; ----------------------------------------------------------------------------
00E225  1               ; Complement the selector returned in Y and save it in $C3.
00E225  1               ; ----------------------------------------------------------------------------
00E225  1               
00E225  1  98               tya                         ; $E225: 98
00E226  1  49 FF            eor #$FF                    ; $E226: 49 FF
00E228  1  85 C3            sta $C3                     ; $E228: 85 C3
00E22A  1               
00E22A  1               ; ----------------------------------------------------------------------------
00E22A  1               ; Test the geometry for the selected entry.
00E22A  1               ;
00E22A  1               ; TestIndexedObjectGeometry returns flags from CMP #$03.
00E22A  1               ; Carry clear means the result is below three.
00E22A  1               ; ----------------------------------------------------------------------------
00E22A  1               
00E22A  1  20 01 E2         jsr TestIndexedObjectGeometry
00E22D  1                                               ; $E22A: 20 01 E2
00E22D  1               
00E22D  1  90 0B            bcc ProcessSelectedObjectState_Clear
00E22F  1                                               ; $E22D: 90 0B
00E22F  1               
00E22F  1               ; ----------------------------------------------------------------------------
00E22F  1               ; Geometry result is at least three.
00E22F  1               ;
00E22F  1               ; Configure value $0F, apply the geometry helpers, and jump to $E2DE.
00E22F  1               ; ----------------------------------------------------------------------------
00E22F  1               
00E22F  1  A9 0F            lda #$0F                    ; $E22F: A9 0F
00E231  1               
00E231  1  20 13 E5         jsr BuildGeometryVector                   ; $E231: 20 13 E5
00E234  1  20 28 E5         jsr StoreCurrentObjectMovement                   ; $E234: 20 28 E5
00E237  1               
00E237  1  4C DE E2         jmp UpdateCurrentObjectAnimationDelay                   ; $E237: 4C DE E2
00E23A  1               
00E23A  1               ; ----------------------------------------------------------------------------
00E23A  1               ; Geometry result is below three.
00E23A  1               ;
00E23A  1               ; Run the state-update helpers, then return to the object-state dispatch path
00E23A  1               ; at $E08B.
00E23A  1               ; ----------------------------------------------------------------------------
00E23A  1               
00E23A  1               ProcessSelectedObjectState_Clear: ; $E23A
00E23A  1  20 D3 E2         jsr ClearCurrentObjectMovement                   ; $E23A: 20 D3 E2
00E23D  1  20 E6 E3         jsr InitializeBaseObjectFromCurrent                   ; $E23D: 20 E6 E3
00E240  1  20 84 E3         jsr ProcessCompactObjectState_Validate                   ; $E240: 20 84 E3
00E243  1               
00E243  1  4C 8B E0         jmp ObjectStateDispatch_NextPath
00E246  1                                               ; $E243: 4C 8B E0
00E246  1               
00E246  1               ; ============================================================================
00E246  1               ; $E246-$E25D
00E246  1               ; Search the object-state entries at $0598-$059B using a caller-supplied
00E246  1               ; selector in Y.
00E246  1               ;
00E246  1               ; Entry:
00E246  1               ;   Y = one-based selector value
00E246  1               ;
00E246  1               ; Exit:
00E246  1               ;   X = selected state-table index, normally $00-$03
00E246  1               ;   Y = adjusted selector value
00E246  1               ;
00E246  1               ; If $0598 is zero, the routine returns immediately without performing the
00E246  1               ; search.
00E246  1               ;
00E246  1               ; The comparison intentionally uses base address $0597,X. Since X begins at
00E246  1               ; four and is decremented after unsuccessful comparisons, the effective
00E246  1               ; entries are $059B, $059A, $0599, and $0598.
00E246  1               ; ============================================================================
00E246  1               
00E246  1               ; ----------------------------------------------------------------------------
00E246  1               ; Contract:
00E246  1               ;   Description: Implements Find Object State For Selector.
00E246  1               ;   Entry: Registers: A, X, Y; Memory: $0598, $0597
00E246  1               ;   Returns/products: Registers/clobbers: A, X, Y; Flags: condition flags may carry result state
00E246  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E246  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00E246  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E246  1               ;          comparison, load, or store path and are not a stable API product.
00E246  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 2.
00E246  1               ; ----------------------------------------------------------------------------
00E246  1               FindObjectStateForSelector:     ; $E246
00E246  1  AD 98 05         lda $0598                   ; $E246: AD 98 05
00E249  1  F0 12            beq FindObjectStateForSelector_Return
00E24B  1                                               ; $E249: F0 12
00E24B  1               
00E24B  1               ; ----------------------------------------------------------------------------
00E24B  1               ; Convert the one-based selector in Y into an odd comparison value:
00E24B  1               ;
00E24B  1               ;   A = ((Y - 1) * 2) + 1
00E24B  1               ;
00E24B  1               ; Y itself remains decremented by one.
00E24B  1               ; ----------------------------------------------------------------------------
00E24B  1               
00E24B  1  88               dey                         ; $E24B: 88
00E24C  1               
00E24C  1  98               tya                         ; $E24C: 98
00E24D  1  0A               asl                         ; $E24D: 0A
00E24E  1  69 01            adc #$01                    ; $E24E: 69 01
00E250  1               
00E250  1               ; ----------------------------------------------------------------------------
00E250  1               ; Search the four state entries in reverse order.
00E250  1               ;
00E250  1               ; The indexed base is deliberately one byte before $0598:
00E250  1               ;
00E250  1               ;   X=$04 -> $059B
00E250  1               ;   X=$03 -> $059A
00E250  1               ;   X=$02 -> $0599
00E250  1               ;   X=$01 -> $0598
00E250  1               ; ----------------------------------------------------------------------------
00E250  1               
00E250  1  A2 04            ldx #$04                    ; $E250: A2 04
00E252  1               
00E252  1               FindObjectStateForSelector_Search: ; $E252
00E252  1  DD 97 05         cmp $0597,x                 ; $E252: DD 97 05
00E255  1  90 03            bcc FindObjectStateForSelector_Previous
00E257  1                                               ; $E255: 90 03
00E257  1               
00E257  1               ; ----------------------------------------------------------------------------
00E257  1               ; The current table value is not greater than A.
00E257  1               ;
00E257  1               ; Decrement Y once more. If it becomes negative, return immediately.
00E257  1               ; Otherwise, keep the current X.
00E257  1               ; ----------------------------------------------------------------------------
00E257  1               
00E257  1  88               dey                         ; $E257: 88
00E258  1  30 03            bmi FindObjectStateForSelector_Return
00E25A  1                                               ; $E258: 30 03
00E25A  1               
00E25A  1               ; ----------------------------------------------------------------------------
00E25A  1               ; Continue searching the preceding table entry.
00E25A  1               ; ----------------------------------------------------------------------------
00E25A  1               
00E25A  1               FindObjectStateForSelector_Previous: ; $E25A
00E25A  1  CA               dex                         ; $E25A: CA
00E25B  1  D0 F5            bne FindObjectStateForSelector_Search
00E25D  1                                               ; $E25B: D0 F5
00E25D  1               
00E25D  1               FindObjectStateForSelector_Return: ; $E25D
00E25D  1  60               rts                         ; $E25D: 60
00E25E  1               
00E25E  1               ; ============================================================================
00E25E  1               ; $E25E-$E294
00E25E  1               ; Find the nearest candidate object from a six-entry object-offset table.
00E25E  1               ;
00E25E  1               ; Entry:
00E25E  1               ;   $C2 = index selecting a signed coordinate adjustment from the overlapping
00E25E  1               ;         tables at $DFCA and $DFCB
00E25E  1               ;
00E25E  1               ; Exit:
00E25E  1               ;   X = selected candidate-table index, $00-$05
00E25E  1               ;   Y = selected object offset:
00E25E  1               ;       $04, $0E, $10, $12, $14, or $16
00E25E  1               ;
00E25E  1               ; Working values:
00E25E  1               ;   $06 = smallest distance found, initialized to $FF
00E25E  1               ;   $05 = candidate-table index associated with that distance
00E25E  1               ;   $41 = current candidate-table index
00E25E  1               ; ============================================================================
00E25E  1               
00E25E  1               ; ----------------------------------------------------------------------------
00E25E  1               ; Contract:
00E25E  1               ;   Description: Implements Find Nearest Candidate Object.
00E25E  1               ;   Entry: Registers: A, X; Memory: $c2, $050a, $dfcb, $053b, $dfca, $06, $41
00E25E  1               ;   Returns/products: Registers/clobbers: A, X, Y
00E25E  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E25E  1               ;   Memory effects: $06, $41, mathtemp05
00E25E  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E25E  1               ;          comparison, load, or store path and are not a stable API product.
00E25E  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00E25E  1               ; ----------------------------------------------------------------------------
00E25E  1               FindNearestCandidateObject:     ; $E25E
00E25E  1  A9 FF            lda #$FF                    ; $E25E: A9 FF
00E260  1  85 06            sta $06                     ; $E260: 85 06
00E262  1                                               ; Initialize best distance to the maximum.
00E262  1               
00E262  1  A2 05            ldx #$05                    ; $E262: A2 05
00E264  1               
00E264  1               ; ----------------------------------------------------------------------------
00E264  1               ; Save the current candidate-table index.
00E264  1               ; ----------------------------------------------------------------------------
00E264  1               
00E264  1               FindNearestCandidateObject_Loop: ; $E264
00E264  1  86 41            stx $41                     ; $E264: 86 41
00E266  1               
00E266  1               ; ----------------------------------------------------------------------------
00E266  1               ; Load the candidate object offset into Y.
00E266  1               ; ----------------------------------------------------------------------------
00E266  1               
00E266  1  BC 95 E2         ldy CandidateObjectOffsetTable,x
00E269  1                                               ; $E266: BC 95 E2
00E269  1               
00E269  1               ; ----------------------------------------------------------------------------
00E269  1               ; Load the signed coordinate-adjustment index.
00E269  1               ; ----------------------------------------------------------------------------
00E269  1               
00E269  1  A6 C2            ldx $C2                     ; $E269: A6 C2
00E26B  1               
00E26B  1               ; ----------------------------------------------------------------------------
00E26B  1               ; Calculate the adjusted horizontal high coordinate:
00E26B  1               ;
00E26B  1               ;   candidateXHi + $DFCB,X
00E26B  1               ;
00E26B  1               ; The result is preserved on the stack.
00E26B  1               ; ----------------------------------------------------------------------------
00E26B  1               
00E26B  1  18               clc                         ; $E26B: 18
00E26C  1               
00E26C  1  B9 0A 05         lda $050A,y                 ; $E26C: B9 0A 05
00E26F  1  7D CB DF         adc $DFCB,x                 ; $E26F: 7D CB DF
00E272  1               
00E272  1  48               pha                         ; $E272: 48
00E273  1               
00E273  1               ; ----------------------------------------------------------------------------
00E273  1               ; Calculate the adjusted vertical high coordinate:
00E273  1               ;
00E273  1               ;   candidateYHi + $DFCA,X
00E273  1               ;
00E273  1               ; The result is passed to $E80B in Y.
00E273  1               ; ----------------------------------------------------------------------------
00E273  1               
00E273  1  18               clc                         ; $E273: 18
00E274  1               
00E274  1  B9 3B 05         lda $053B,y                 ; $E274: B9 3B 05
00E277  1  7D CA DF         adc $DFCA,x                 ; $E277: 7D CA DF
00E27A  1               
00E27A  1  A8               tay                         ; $E27A: A8
00E27B  1               
00E27B  1               ; ----------------------------------------------------------------------------
00E27B  1               ; Restore the adjusted horizontal value into X and calculate a distance or
00E27B  1               ; magnitude through $E80B.
00E27B  1               ; ----------------------------------------------------------------------------
00E27B  1               
00E27B  1  68               pla                         ; $E27B: 68
00E27C  1  AA               tax                         ; $E27C: AA
00E27D  1               
00E27D  1  20 0B E8         jsr CalculateVectorMagnitude                   ; $E27D: 20 0B E8
00E280  1               
00E280  1               ; ----------------------------------------------------------------------------
00E280  1               ; Keep this candidate only when its returned distance in A is lower than the
00E280  1               ; current best distance in $06.
00E280  1               ; ----------------------------------------------------------------------------
00E280  1               
00E280  1  C5 06            cmp $06                     ; $E280: C5 06
00E282  1  B0 06            bcs FindNearestCandidateObject_Next
00E284  1                                               ; $E282: B0 06
00E284  1               
00E284  1  85 06            sta $06                     ; $E284: 85 06
00E286  1               
00E286  1  A5 41            lda $41                     ; $E286: A5 41
00E288  1  85 05            sta MathTemp05              ; $E288: 85 05
00E28A  1                                               ; Save the winning candidate-table index.
00E28A  1               
00E28A  1               ; ----------------------------------------------------------------------------
00E28A  1               ; Continue through all six candidate entries, from index five down to zero.
00E28A  1               ; ----------------------------------------------------------------------------
00E28A  1               
00E28A  1               FindNearestCandidateObject_Next: ; $E28A
00E28A  1  A6 41            ldx $41                     ; $E28A: A6 41
00E28C  1  CA               dex                         ; $E28C: CA
00E28D  1  10 D5            bpl FindNearestCandidateObject_Loop
00E28F  1                                               ; $E28D: 10 D5
00E28F  1               
00E28F  1               ; ----------------------------------------------------------------------------
00E28F  1               ; Return the winning candidate-table index in X and its object offset in Y.
00E28F  1               ; ----------------------------------------------------------------------------
00E28F  1               
00E28F  1  A6 05            ldx MathTemp05              ; $E28F: A6 05
00E291  1  BC 95 E2         ldy CandidateObjectOffsetTable,x
00E294  1                                               ; $E291: BC 95 E2
00E294  1               
00E294  1  60               rts                         ; $E294: 60
00E295  1               
00E295  1               ; ============================================================================
00E295  1               ; $E295-$E29A
00E295  1               ; Candidate object offsets searched by FindNearestCandidateObject.
00E295  1               ;
00E295  1               ; The values are even object-array offsets. Their compact indices are obtained
00E295  1               ; by dividing by two.
00E295  1               ; ============================================================================
00E295  1               
00E295  1               CandidateObjectOffsetTable:     ; $E295
00E295  1  04               .byte $04                   ; Compact index $02
00E296  1  0E               .byte $0E                   ; Compact index $07
00E297  1  10               .byte $10                   ; Compact index $08
00E298  1  12               .byte $12                   ; Compact index $09
00E299  1  14               .byte $14                   ; Compact index $0A
00E29A  1  16               .byte $16                   ; Compact index $0B
00E29B  1               
00E29B  1               ; ============================================================================
00E29B  1               ; $E29B-$E2A4
00E29B  1               ; Dispatch an inline command for a caller-supplied object offset.
00E29B  1               ;
00E29B  1               ; Entry:
00E29B  1               ;   X = object or event offset
00E29B  1               ;
00E29B  1               ; Inline caller data:
00E29B  1               ;   The bytes immediately following the caller's JSR are interpreted by
00E29B  1               ;   $E99A. Existing call sites provide records such as:
00E29B  1               ;
00E29B  1               ;       .byte $00
00E29B  1               ;       .word HandlerAddress - 1
00E29B  1               ;
00E29B  1               ; Operation:
00E29B  1               ;   1. Preserve X in zero-page $06.
00E29B  1               ;   2. Call $E99A to locate or decode the caller's inline data.
00E29B  1               ;   3. Restore X.
00E29B  1               ;   4. Tail-call the command dispatcher at $EB0D.
00E29B  1               ;
00E29B  1               ; The jump to $EB0D enters three bytes after the normal QueueInlineObjectEvent entry, which
00E29B  1               ; suggests $E99A has already completed the inline-record setup normally
00E29B  1               ; performed by QueueInlineObjectEvent.
00E29B  1               ; ============================================================================
00E29B  1               
00E29B  1               ; ----------------------------------------------------------------------------
00E29B  1               ; Contract:
00E29B  1               ;   Description: Implements Dispatch Inline Object Command.
00E29B  1               ;   Entry: Registers: X; Memory: $06
00E29B  1               ;   Returns/products: Registers/clobbers: X
00E29B  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E29B  1               ;   Memory effects: $06
00E29B  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E29B  1               ;          comparison, load, or store path and are not a stable API product.
00E29B  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 3.
00E29B  1               ; ----------------------------------------------------------------------------
00E29B  1               DispatchInlineObjectCommand:    ; $E29B
00E29B  1  86 06            stx $06                     ; $E29B: 86 06
00E29D  1                                               ; Preserve the caller-supplied object offset.
00E29D  1               
00E29D  1  20 9A E9         jsr DecodeInlineParameters                   ; $E29D: 20 9A E9
00E2A0  1                                               ; Decode or locate the inline record following
00E2A0  1                                               ; the caller's JSR.
00E2A0  1               
00E2A0  1  A6 06            ldx $06                     ; $E2A0: A6 06
00E2A2  1                                               ; Restore the object offset.
00E2A2  1               
00E2A2  1  4C 0D EB         jmp QueueDecodedObjectEvent                   ; $E2A2: 4C 0D EB
00E2A5  1                                               ; Tail-call the command dispatcher after its
00E2A5  1                                               ; normal inline-record setup entry.
00E2A5  1               
00E2A5  1               ; ============================================================================
00E2A5  1               ; $E2A5-$E2D2
00E2A5  1               ; Calculate scaled coordinate differences between the base object and the
00E2A5  1               ; object selected by X.
00E2A5  1               ;
00E2A5  1               ; Entry:
00E2A5  1               ;   X = object-array offset
00E2A5  1               ;
00E2A5  1               ; Exit:
00E2A5  1               ;   A = scaled horizontal high/result byte
00E2A5  1               ;   Y = scaled vertical high/result byte
00E2A5  1               ;
00E2A5  1               ; Working values:
00E2A5  1               ;   $AE = horizontal low difference
00E2A5  1               ;   $B0 = vertical low difference
00E2A5  1               ;
00E2A5  1               ; Both signed 16-bit differences are shifted left twice across their low and
00E2A5  1               ; high bytes. The low result bytes remain in $AE and $B0.
00E2A5  1               ; ============================================================================
00E2A5  1               
00E2A5  1               CalculateObjectCoordinateDifference: ; $E2A5
00E2A5  1  38               sec                         ; $E2A5: 38
00E2A6  1               
00E2A6  1               ; ----------------------------------------------------------------------------
00E2A6  1               ; Calculate the signed vertical difference:
00E2A6  1               ;
00E2A6  1               ;   baseY - objectY
00E2A6  1               ;
00E2A6  1               ; Low byte:
00E2A6  1               ;   $053A - $053A,X
00E2A6  1               ;
00E2A6  1               ; High byte:
00E2A6  1               ;   $053B - $053B,X
00E2A6  1               ; ----------------------------------------------------------------------------
00E2A6  1               
00E2A6  1  AD 3A 05         lda $053A                   ; $E2A6: AD 3A 05
00E2A9  1  FD 3A 05         sbc $053A,x                 ; $E2A9: FD 3A 05
00E2AC  1  85 B0            sta $B0                     ; $E2AC: 85 B0
00E2AE  1               
00E2AE  1  AD 3B 05         lda $053B                   ; $E2AE: AD 3B 05
00E2B1  1  FD 3B 05         sbc $053B,x                 ; $E2B1: FD 3B 05
00E2B4  1               
00E2B4  1               ; ----------------------------------------------------------------------------
00E2B4  1               ; Multiply the signed vertical difference by four.
00E2B4  1               ;
00E2B4  1               ; First shift:
00E2B4  1               ;   ASL $B0
00E2B4  1               ;   ROL A
00E2B4  1               ;
00E2B4  1               ; Second shift:
00E2B4  1               ;   ASL $B0
00E2B4  1               ;   ADC #$00
00E2B4  1               ;
00E2B4  1               ; The second ADC incorporates carry from the low-byte shift into the high byte.
00E2B4  1               ; ----------------------------------------------------------------------------
00E2B4  1               
00E2B4  1  06 B0            asl $B0                     ; $E2B4: 06 B0
00E2B6  1  2A               rol                         ; $E2B6: 2A
00E2B7  1               
00E2B7  1  06 B0            asl $B0                     ; $E2B7: 06 B0
00E2B9  1  69 00            adc #$00                    ; $E2B9: 69 00
00E2BB  1               
00E2BB  1  A8               tay                         ; $E2BB: A8
00E2BC  1                                               ; Y = scaled vertical high/result byte.
00E2BC  1               
00E2BC  1               ; ----------------------------------------------------------------------------
00E2BC  1               ; Calculate the signed horizontal difference:
00E2BC  1               ;
00E2BC  1               ;   baseX - objectX
00E2BC  1               ;
00E2BC  1               ; Low byte:
00E2BC  1               ;   $0509 - $0509,X
00E2BC  1               ;
00E2BC  1               ; High byte:
00E2BC  1               ;   $050A - $050A,X
00E2BC  1               ; ----------------------------------------------------------------------------
00E2BC  1               
00E2BC  1  38               sec                         ; $E2BC: 38
00E2BD  1               
00E2BD  1  AD 09 05         lda $0509                   ; $E2BD: AD 09 05
00E2C0  1  FD 09 05         sbc $0509,x                 ; $E2C0: FD 09 05
00E2C3  1  85 AE            sta CalculatedCoordinateLow                     ; $E2C3: 85 AE
00E2C5  1               
00E2C5  1  AD 0A 05         lda $050A                   ; $E2C5: AD 0A 05
00E2C8  1  FD 0A 05         sbc $050A,x                 ; $E2C8: FD 0A 05
00E2CB  1               
00E2CB  1               ; ----------------------------------------------------------------------------
00E2CB  1               ; Multiply the signed horizontal difference by four.
00E2CB  1               ; ----------------------------------------------------------------------------
00E2CB  1               
00E2CB  1  06 AE            asl CalculatedCoordinateLow                     ; $E2CB: 06 AE
00E2CD  1  2A               rol                         ; $E2CD: 2A
00E2CE  1               
00E2CE  1  06 AE            asl CalculatedCoordinateLow                     ; $E2CE: 06 AE
00E2D0  1  69 00            adc #$00                    ; $E2D0: 69 00
00E2D2  1               
00E2D2  1  60               rts                         ; $E2D2: 60
00E2D3  1               
00E2D3  1               ; ============================================================================
00E2D3  1               ; $E2D3-$E2DF
00E2D3  1               ; Clear the current object's two movement or velocity state bytes.
00E2D3  1               ;
00E2D3  1               ; Entry:
00E2D3  1               ;   CurrentObjectIndex = object-array offset
00E2D3  1               ;
00E2D3  1               ; Exit:
00E2D3  1               ;   A = $00
00E2D3  1               ;   X = CurrentObjectIndex
00E2D3  1               ;   Z = set
00E2D3  1               ;
00E2D3  1               ; Modified object fields:
00E2D3  1               ;   $056D,X = $00
00E2D3  1               ;   $056E,X = $00
00E2D3  1               ; ============================================================================
00E2D3  1               
00E2D3  1               ; ----------------------------------------------------------------------------
00E2D3  1               ; Contract:
00E2D3  1               ;   Description: Clears or resets Current Object Movement.
00E2D3  1               ;   Entry: Registers: A; Memory: currentobjectindex
00E2D3  1               ;   Returns/products: Registers/clobbers: A, X
00E2D3  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E2D3  1               ;   Memory effects: $056d, $056e
00E2D3  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E2D3  1               ;          comparison, load, or store path and are not a stable API product.
00E2D3  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 8.
00E2D3  1               ; ----------------------------------------------------------------------------
00E2D3  1               ClearCurrentObjectMovement:     ; $E2D3
00E2D3  1  A6 E1            ldx CurrentObjectIndex      ; $E2D3: A6 E1
00E2D5  1               
00E2D5  1  A9 00            lda #$00                    ; $E2D5: A9 00
00E2D7  1  9D 6D 05         sta $056D,x                 ; $E2D7: 9D 6D 05
00E2DA  1  9D 6E 05         sta $056E,x                 ; $E2DA: 9D 6E 05
00E2DD  1               
00E2DD  1  60               rts                         ; $E2DD: 60
00E2DE  1               
00E2DE  1               ; ============================================================================
00E2DE  1               ; $E2DE-$E312
00E2DE  1               ; Update the current object's animation frame and return a delay selected from
00E2DE  1               ; a table.
00E2DE  1               ;
00E2DE  1               ; Entry:
00E2DE  1               ;   CurrentObjectIndex = object-array offset
00E2DE  1               ;
00E2DE  1               ; Return:
00E2DE  1               ;   A = selector-specific delay from $E329,Y
00E2DE  1               ;
00E2DE  1               ;   If either call to $E6B7 returns carry set:
00E2DE  1               ;       A = $06
00E2DE  1               ; ============================================================================
00E2DE  1               
00E2DE  1               ; ----------------------------------------------------------------------------
00E2DE  1               ; Contract:
00E2DE  1               ;   Description: Updates Current Object Animation Delay.
00E2DE  1               ;   Entry: Registers: A, X; Memory: currentobjectindex, $056e, $056d, $039a
00E2DE  1               ;   Returns/products: Registers/clobbers: A, X, Y
00E2DE  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E2DE  1               ;   Memory effects: $039a
00E2DE  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E2DE  1               ;          comparison, load, or store path and are not a stable API product.
00E2DE  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 4.
00E2DE  1               ; ----------------------------------------------------------------------------
00E2DE  1               UpdateCurrentObjectAnimationDelay: ; $E2DE
00E2DE  1  A6 E1            ldx CurrentObjectIndex      ; $E2DE: A6 E1
00E2E0  1               
00E2E0  1               ; ----------------------------------------------------------------------------
00E2E0  1               ; Derive a preliminary three-bit animation selector from the current object's
00E2E0  1               ; state bytes at $056D/$056E.
00E2E0  1               ;
00E2E0  1               ; Bit flow:
00E2E0  1               ;
00E2E0  1               ;   ASL $056E,X puts its high bit in carry.
00E2E0  1               ;   ROL $056D,X shifts that carry into A.
00E2E0  1               ;   A second ROL expands the selector.
00E2E0  1               ; ----------------------------------------------------------------------------
00E2E0  1               
00E2E0  1  BD 6E 05         lda $056E,x                 ; $E2E0: BD 6E 05
00E2E3  1  0A               asl                         ; $E2E3: 0A
00E2E4  1               
00E2E4  1  BD 6D 05         lda $056D,x                 ; $E2E4: BD 6D 05
00E2E7  1  2A               rol                         ; $E2E7: 2A
00E2E8  1  2A               rol                         ; $E2E8: 2A
00E2E9  1               
00E2E9  1  48               pha                         ; $E2E9: 48
00E2EA  1                                               ; Preserve the preliminary selector.
00E2EA  1               
00E2EA  1               ; ----------------------------------------------------------------------------
00E2EA  1               ; Update or test the current object through $E6B7.
00E2EA  1               ; ----------------------------------------------------------------------------
00E2EA  1               
00E2EA  1  20 B7 E6         jsr ClearMovementTransforms                   ; $E2EA: 20 B7 E6
00E2ED  1               
00E2ED  1  68               pla                         ; $E2ED: 68
00E2EE  1  B0 20            bcs UpdateCurrentObjectAnimationDelay_Default
00E2F0  1                                               ; $E2EE: B0 20
00E2F0  1               
00E2F0  1               ; ----------------------------------------------------------------------------
00E2F0  1               ; Incorporate whether X is at least $15 into the selector.
00E2F0  1               ;
00E2F0  1               ; CPX sets carry, then ROL shifts that condition into A.
00E2F0  1               ; ----------------------------------------------------------------------------
00E2F0  1               
00E2F0  1  E0 15            cpx #$15                    ; $E2F0: E0 15
00E2F2  1  2A               rol                         ; $E2F2: 2A
00E2F3  1               
00E2F3  1  29 07            and #$07                    ; $E2F3: 29 07
00E2F5  1  A8               tay                         ; $E2F5: A8
00E2F6  1                                               ; Y selects one of eight animation ranges.
00E2F6  1               
00E2F6  1               ; ----------------------------------------------------------------------------
00E2F6  1               ; Increment the current frame while preserving its original value in A for
00E2F6  1               ; the range comparisons.
00E2F6  1               ; ----------------------------------------------------------------------------
00E2F6  1               
00E2F6  1  BD 9A 03         lda $039A,x                 ; $E2F6: BD 9A 03
00E2F9  1  FE 9A 03         inc $039A,x                 ; $E2F9: FE 9A 03
00E2FC  1               
00E2FC  1               ; ----------------------------------------------------------------------------
00E2FC  1               ; If the original frame is at or beyond its upper limit, reset it to the base
00E2FC  1               ; frame.
00E2FC  1               ;
00E2FC  1               ; If it is between the base and upper limit, keep the incremented frame.
00E2FC  1               ;
00E2FC  1               ; If it is below the base frame, reset it to the base frame.
00E2FC  1               ; ----------------------------------------------------------------------------
00E2FC  1               
00E2FC  1  D9 21 E3         cmp CurrentObjectAnimationLimitTable,y
00E2FF  1                                               ; $E2FC: D9 21 E3
00E2FF  1  B0 05            bcs UpdateCurrentObjectAnimationDelay_Reset
00E301  1                                               ; $E2FF: B0 05
00E301  1               
00E301  1  D9 19 E3         cmp CurrentObjectAnimationBaseTable,y
00E304  1                                               ; $E301: D9 19 E3
00E304  1  B0 06            bcs UpdateCurrentObjectAnimationDelay_LoadDelay
00E306  1                                               ; $E304: B0 06
00E306  1               
00E306  1               UpdateCurrentObjectAnimationDelay_Reset: ; $E306
00E306  1  B9 19 E3         lda CurrentObjectAnimationBaseTable,y
00E309  1                                               ; $E306: B9 19 E3
00E309  1  9D 9A 03         sta $039A,x                 ; $E309: 9D 9A 03
00E30C  1               
00E30C  1               ; ----------------------------------------------------------------------------
00E30C  1               ; Return the delay associated with this animation range.
00E30C  1               ; ----------------------------------------------------------------------------
00E30C  1               
00E30C  1               UpdateCurrentObjectAnimationDelay_LoadDelay: ; $E30C
00E30C  1  B9 29 E3         lda CurrentObjectAnimationDelayTable,y
00E30F  1                                               ; $E30C: B9 29 E3
00E30F  1  60               rts                         ; $E30F: 60
00E310  1               
00E310  1               ; ----------------------------------------------------------------------------
00E310  1               ; Carry-set fallback from $E6B7.
00E310  1               ; ----------------------------------------------------------------------------
00E310  1               
00E310  1               UpdateCurrentObjectAnimationDelay_Default: ; $E310
00E310  1  A9 06            lda #$06                    ; $E310: A9 06
00E312  1  60               rts                         ; $E312: 60
00E313  1               
00E313  1               ; ============================================================================
00E313  1               ; $E313-$E318
00E313  1               ; Update the current object's animation and immediately wait for the returned
00E313  1               ; delay.
00E313  1               ;
00E313  1               ; This is a compact wrapper around UpdateCurrentObjectAnimationDelay and
00E313  1               ; $EB41.
00E313  1               ; ============================================================================
00E313  1               
00E313  1               ; ----------------------------------------------------------------------------
00E313  1               ; Contract:
00E313  1               ;   Description: Updates Current Object Animation And Wait.
00E313  1               ;   Entry: No register input inferred
00E313  1               ;   Returns/products: No direct product inferred
00E313  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E313  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00E313  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E313  1               ;          comparison, load, or store path and are not a stable API product.
00E313  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 2.
00E313  1               ; ----------------------------------------------------------------------------
00E313  1               UpdateCurrentObjectAnimationAndWait: ; $E313
00E313  1  20 DE E2         jsr UpdateCurrentObjectAnimationDelay
00E316  1                                               ; $E313: 20 DE E2
00E316  1               
00E316  1  4C 41 EB         jmp StoreObjectEventBankValue                   ; $E316: 4C 41 EB
00E319  1                                               ; Tail-call the delay helper.
00E319  1               
00E319  1               ; ============================================================================
00E319  1               ; $E319-$E320
00E319  1               ; Base/reset frames for the eight current-object animation ranges.
00E319  1               ; ============================================================================
00E319  1               
00E319  1               CurrentObjectAnimationBaseTable: ; $E319
00E319  1  61 32 64 35      .byte $61,$32,$64,$35
00E31D  1  5C 3B 5C 38      .byte $5C,$3B,$5C,$38
00E321  1               
00E321  1               ; ============================================================================
00E321  1               ; $E321-$E328
00E321  1               ; Exclusive upper frame limits for the eight animation ranges.
00E321  1               ; ============================================================================
00E321  1               
00E321  1               CurrentObjectAnimationLimitTable: ; $E321
00E321  1  63 34 66 37      .byte $63,$34,$66,$37
00E325  1  5D 3D 5D 3A      .byte $5D,$3D,$5D,$3A
00E329  1               
00E329  1               ; ============================================================================
00E329  1               ; $E329-$E330
00E329  1               ; Delay values associated with the eight animation ranges.
00E329  1               ; ============================================================================
00E329  1               
00E329  1               CurrentObjectAnimationDelayTable: ; $E329
00E329  1  06 06 06 06      .byte $06,$06,$06,$06
00E32D  1  09 06 09 06      .byte $09,$06,$09,$06
00E331  1               
00E331  1               ; ============================================================================
00E331  1               ; $E331-$E346
00E331  1               ; Find an object-state entry equal to twice the selected compact state.
00E331  1               ;
00E331  1               ; Entry:
00E331  1               ;   $C2 = compact state value
00E331  1               ;
00E331  1               ; Search:
00E331  1               ;   $059B, $059A, $0599, $0598
00E331  1               ;
00E331  1               ; If a matching entry is found:
00E331  1               ;   1. Copy $C2 to StateSelector.
00E331  1               ;   2. Call the state-marker helper at $CD2E.
00E331  1               ;
00E331  1               ; If no entry matches:
00E331  1               ;   Return without changing StateSelector.
00E331  1               ;
00E331  1               ; Exit:
00E331  1               ;   X = matching object-state index, or $FF if no match was found
00E331  1               ; ============================================================================
00E331  1               
00E331  1               ; ----------------------------------------------------------------------------
00E331  1               ; Contract:
00E331  1               ;   Description: Implements Find And Queue Selected State.
00E331  1               ;   Entry: Registers: A, X; Memory: $c2, $0598
00E331  1               ;   Returns/products: Registers/clobbers: A, X; Flags: condition flags may carry result state
00E331  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E331  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00E331  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E331  1               ;          comparison, load, or store path and are not a stable API product.
00E331  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00E331  1               ; ----------------------------------------------------------------------------
00E331  1               FindAndQueueSelectedState:      ; $E331
00E331  1  A2 03            ldx #$03                    ; $E331: A2 03
00E333  1               
00E333  1               ; ----------------------------------------------------------------------------
00E333  1               ; Double the compact state value.
00E333  1               ;
00E333  1               ; The loop branches back to the CMP at $E336, not to LDA/ASL. The doubled
00E333  1               ; value therefore remains in A for all four comparisons.
00E333  1               ; ----------------------------------------------------------------------------
00E333  1               
00E333  1  A5 C2            lda $C2                     ; $E333: A5 C2
00E335  1  0A               asl                         ; $E335: 0A
00E336  1               
00E336  1               FindAndQueueSelectedState_Search: ; $E336
00E336  1  DD 98 05         cmp $0598,x                 ; $E336: DD 98 05
00E339  1  F0 04            beq FindAndQueueSelectedState_Found
00E33B  1                                               ; $E339: F0 04
00E33B  1               
00E33B  1  CA               dex                         ; $E33B: CA
00E33C  1  10 F8            bpl FindAndQueueSelectedState_Search
00E33E  1                                               ; $E33C: 10 F8
00E33E  1               
00E33E  1               ; ----------------------------------------------------------------------------
00E33E  1               ; No matching state entry was found.
00E33E  1               ; ----------------------------------------------------------------------------
00E33E  1               
00E33E  1  60               rts                         ; $E33E: 60
00E33F  1               
00E33F  1               ; ----------------------------------------------------------------------------
00E33F  1               ; Matching entry found.
00E33F  1               ;
00E33F  1               ; Restore the undoubled state value from $C2, save it in StateSelector, and
00E33F  1               ; invoke the state-marker helper at $CD2E.
00E33F  1               ; ----------------------------------------------------------------------------
00E33F  1               
00E33F  1               FindAndQueueSelectedState_Found: ; $E33F
00E33F  1  A5 C2            lda $C2                     ; $E33F: A5 C2
00E341  1  85 72            sta StateSelector           ; $E341: 85 72
00E343  1               
00E343  1  20 2E CD         jsr QueueSelectedStateMarker            ; $E343: 20 2E CD
00E346  1               
00E346  1  60               rts                         ; $E346: 60
00E347  1               
00E347  1               ; ============================================================================
00E347  1               ; $E347-$E3AB
00E347  1               ; Validate and consume the compact object-state selected in $C2.
00E347  1               ;
00E347  1               ; The routine inspects the corresponding entries in $0598-$059B and $95-$98,
00E347  1               ; may search for an alternate state, updates PendingScoreIncrement, marks an object
00E347  1               ; state inactive, and advances the alternate state sequence.
00E347  1               ;
00E347  1               ; Entry:
00E347  1               ;   $C2 = compact object-state index
00E347  1               ; ============================================================================
00E347  1               
00E347  1               ; ----------------------------------------------------------------------------
00E347  1               ; Contract:
00E347  1               ;   Description: Processes Compact Object State.
00E347  1               ;   Entry: Registers: A, X, Y; Memory: $c2, $0598, $95, objecttransitionstate, secondarysequencestate, $c3
00E347  1               ;   Returns/products: Registers/clobbers: A, X, Y
00E347  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E347  1               ;   Memory effects: $c3, $c2, $96, $97, $98, pendingscoreincrement
00E347  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E347  1               ;          comparison, load, or store path and are not a stable API product.
00E347  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00E347  1               ; ----------------------------------------------------------------------------
00E347  1               ProcessCompactObjectState:      ; $E347
00E347  1  A6 C2            ldx $C2                     ; $E347: A6 C2
00E349  1               
00E349  1               ; ----------------------------------------------------------------------------
00E349  1               ; Compact state values of four or greater are rejected.
00E349  1               ; ----------------------------------------------------------------------------
00E349  1               
00E349  1  E0 04            cpx #$04                    ; $E349: E0 04
00E34B  1  B0 5E            bcs ProcessCompactObjectState_Return
00E34D  1                                               ; $E34B: B0 5E
00E34D  1               
00E34D  1               ; ----------------------------------------------------------------------------
00E34D  1               ; Reject inactive state-table entries.
00E34D  1               ; ----------------------------------------------------------------------------
00E34D  1               
00E34D  1  BD 98 05         lda $0598,x                 ; $E34D: BD 98 05
00E350  1  30 59            bmi ProcessCompactObjectState_Return
00E352  1                                               ; $E350: 30 59
00E352  1               
00E352  1               ; ----------------------------------------------------------------------------
00E352  1               ; Reject entries whose corresponding zero-page state at $95-$98 is nonzero.
00E352  1               ; ----------------------------------------------------------------------------
00E352  1               
00E352  1  B5 95            lda $95,x                   ; $E352: B5 95
00E354  1  D0 55            bne ProcessCompactObjectState_Return
00E356  1                                               ; $E354: D0 55
00E356  1               
00E356  1               ; ----------------------------------------------------------------------------
00E356  1               ; Preserve the selected compact index.
00E356  1               ;
00E356  1               ; Index zero uses the shared PendingScoreIncrement path at $E380.
00E356  1               ; ----------------------------------------------------------------------------
00E356  1               
00E356  1  86 C3            stx $C3                     ; $E356: 86 C3
00E358  1  F0 26            beq ProcessCompactObjectState_SavePending
00E35A  1                                               ; $E358: F0 26
00E35A  1               
00E35A  1               ; ============================================================================
00E35A  1               ; $E35A
00E35A  1               ; Search for an alternate state entry.
00E35A  1               ; ============================================================================
00E35A  1               
00E35A  1               ; ----------------------------------------------------------------------------
00E35A  1               ; Contract:
00E35A  1               ;   Description: Processes Compact Object State  Find Alternate.
00E35A  1               ;   Entry: Registers: A, X, Y; Memory: $c2, objecttransitionstate, secondarysequencestate, $c3, $0598
00E35A  1               ;   Returns/products: Registers/clobbers: A, X, Y
00E35A  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E35A  1               ;   Memory effects: $c2, $c3, $96, $97, $98, pendingscoreincrement
00E35A  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E35A  1               ;          comparison, load, or store path and are not a stable API product.
00E35A  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00E35A  1               ; ----------------------------------------------------------------------------
00E35A  1               ProcessCompactObjectState_FindAlternate: ; $E35A
00E35A  1  A9 04            lda #$04                    ; $E35A: A9 04
00E35C  1  85 C2            sta $C2                     ; $E35C: 85 C2
00E35E  1               
00E35E  1  A9 00            lda #$00                    ; $E35E: A9 00
00E360  1  85 C3            sta $C3                     ; $E360: 85 C3
00E362  1               
00E362  1  85 96            sta $96                     ; $E362: 85 96
00E364  1  85 97            sta $97                     ; $E364: 85 97
00E366  1  85 98            sta $98                     ; $E366: 85 98
00E368  1               
00E368  1               ; ----------------------------------------------------------------------------
00E368  1               ; A is zero, so this branch is always taken to the state comparison at $E379.
00E368  1               ;
00E368  1               ; The entry at $E36A is also called directly by earlier code.
00E368  1               ; ----------------------------------------------------------------------------
00E368  1               
00E368  1  F0 0F            beq ProcessCompactObjectState_CompareState64
00E36A  1                                               ; $E368: F0 0F
00E36A  1               
00E36A  1               ; ============================================================================
00E36A  1               ; $E36A
00E36A  1               ; Alternate entry used by the main object-state dispatcher.
00E36A  1               ;
00E36A  1               ; Test whether the selector derived from $C2 has a valid matching object state.
00E36A  1               ; ============================================================================
00E36A  1               
00E36A  1               ; ----------------------------------------------------------------------------
00E36A  1               ; Contract:
00E36A  1               ;   Description: Processes Compact Object State  Test Selector.
00E36A  1               ;   Entry: Registers: A, X, Y; Memory: $c2, objecttransitionstate, secondarysequencestate, $c3, $0598
00E36A  1               ;   Returns/products: Registers/clobbers: A, X, Y
00E36A  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E36A  1               ;   Memory effects: $c3, pendingscoreincrement, $c2, $0598, stateselector
00E36A  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E36A  1               ;          comparison, load, or store path and are not a stable API product.
00E36A  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00E36A  1               ; ----------------------------------------------------------------------------
00E36A  1               ProcessCompactObjectState_TestSelector: ; $E36A
00E36A  1  A4 C2            ldy $C2                     ; $E36A: A4 C2
00E36C  1  88               dey                         ; $E36C: 88
00E36D  1  84 C3            sty $C3                     ; $E36D: 84 C3
00E36F  1  C8               iny                         ; $E36F: C8
00E370  1               
00E370  1  20 46 E2         jsr FindObjectStateForSelector
00E373  1                                               ; $E370: 20 46 E2
00E373  1               
00E373  1  10 36            bpl ProcessCompactObjectState_Return
00E375  1                                               ; $E373: 10 36
00E375  1               
00E375  1  A5 6E            lda ObjectTransitionState                 ; $E375: A5 6E
00E377  1  D0 32            bne ProcessCompactObjectState_Return
00E379  1                                               ; $E377: D0 32
00E379  1               
00E379  1               ; ----------------------------------------------------------------------------
00E379  1               ; Compare SecondarySequenceState against two.
00E379  1               ;
00E379  1               ; The subtraction result becomes the value stored in PendingScoreIncrement.
00E379  1               ; ----------------------------------------------------------------------------
00E379  1               
00E379  1               ProcessCompactObjectState_CompareState64: ; $E379
00E379  1  38               sec                         ; $E379: 38
00E37A  1               
00E37A  1  A5 64            lda SecondarySequenceState                 ; $E37A: A5 64
00E37C  1  E9 02            sbc #$02                    ; $E37C: E9 02
00E37E  1  D0 1D            bne ProcessCompactObjectState_Consume
00E380  1                                               ; $E37E: D0 1D
00E380  1               
00E380  1               ; ----------------------------------------------------------------------------
00E380  1               ; Store the subtraction result in PendingScoreIncrement.
00E380  1               ;
00E380  1               ; Entry from $E358 uses A from LDA $95,X, which is known to be zero.
00E380  1               ; Therefore both paths normally store zero.
00E380  1               ; ----------------------------------------------------------------------------
00E380  1               
00E380  1               ProcessCompactObjectState_SavePending: ; $E380
00E380  1  85 65            sta PendingScoreIncrement        ; $E380: 85 65
00E382  1  F0 19            beq ProcessCompactObjectState_Consume
00E384  1                                               ; $E382: F0 19
00E384  1               
00E384  1               ; ============================================================================
00E384  1               ; $E384
00E384  1               ; Validate the selected state when ObjectTransitionState is nonzero.
00E384  1               ;
00E384  1               ; This entry is also called independently from $E240.
00E384  1               ; ============================================================================
00E384  1               
00E384  1               ; ----------------------------------------------------------------------------
00E384  1               ; Contract:
00E384  1               ;   Description: Processes Compact Object State  Validate.
00E384  1               ;   Entry: Registers: A, X, Y; Memory: objecttransitionstate, $c3, $0598, $c2
00E384  1               ;   Returns/products: Registers/clobbers: A, X, Y
00E384  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E384  1               ;   Memory effects: $c2, $0598, stateselector
00E384  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E384  1               ;          comparison, load, or store path and are not a stable API product.
00E384  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00E384  1               ; ----------------------------------------------------------------------------
00E384  1               ProcessCompactObjectState_Validate: ; $E384
00E384  1  A5 6E            lda ObjectTransitionState                 ; $E384: A5 6E
00E386  1  F0 09            beq ProcessCompactObjectState_LoadEntry
00E388  1                                               ; $E386: F0 09
00E388  1               
00E388  1  A5 C3            lda $C3                     ; $E388: A5 C3
00E38A  1  A8               tay                         ; $E38A: A8
00E38B  1  C8               iny                         ; $E38B: C8
00E38C  1               
00E38C  1  20 46 E2         jsr FindObjectStateForSelector
00E38F  1                                               ; $E38C: 20 46 E2
00E38F  1               
00E38F  1  30 1A            bmi ProcessCompactObjectState_Return
00E391  1                                               ; $E38F: 30 1A
00E391  1               
00E391  1               ; ----------------------------------------------------------------------------
00E391  1               ; Load the selected state entry, divide it by two, and save the compact result
00E391  1               ; in $C2.
00E391  1               ; ----------------------------------------------------------------------------
00E391  1               
00E391  1               ProcessCompactObjectState_LoadEntry: ; $E391
00E391  1  A6 C3            ldx $C3                     ; $E391: A6 C3
00E393  1               
00E393  1  BD 98 05         lda $0598,x                 ; $E393: BD 98 05
00E396  1  4A               lsr                         ; $E396: 4A
00E397  1  85 C2            sta $C2                     ; $E397: 85 C2
00E399  1               
00E399  1               ; ----------------------------------------------------------------------------
00E399  1               ; If the original state byte was even, carry is clear and processing branches
00E399  1               ; backward to the found path in FindAndQueueSelectedState at $E33F.
00E399  1               ; ----------------------------------------------------------------------------
00E399  1               
00E399  1  90 A4            bcc FindAndQueueSelectedState_Found
00E39B  1                                               ; $E399: 90 A4
00E39B  1               
00E39B  1               ; ----------------------------------------------------------------------------
00E39B  1               ; Odd state values increment the compact state before being consumed.
00E39B  1               ; ----------------------------------------------------------------------------
00E39B  1               
00E39B  1  E6 C2            inc $C2                     ; $E39B: E6 C2
00E39D  1               
00E39D  1               ; ============================================================================
00E39D  1               ; $E39D
00E39D  1               ; Mark the selected object-state entry inactive and advance the state sequence.
00E39D  1               ; ============================================================================
00E39D  1               
00E39D  1               ProcessCompactObjectState_Consume: ; $E39D
00E39D  1  A6 C3            ldx $C3                     ; $E39D: A6 C3
00E39F  1               
00E39F  1  A9 FF            lda #$FF                    ; $E39F: A9 FF
00E3A1  1  9D 98 05         sta $0598,x                 ; $E3A1: 9D 98 05
00E3A4  1               
00E3A4  1  A6 C2            ldx $C2                     ; $E3A4: A6 C2
00E3A6  1  86 72            stx StateSelector           ; $E3A6: 86 72
00E3A8  1               
00E3A8  1  20 E4 CC         jsr AdvanceAlternateStateSequence
00E3AB  1                                               ; $E3A8: 20 E4 CC
00E3AB  1                                               ; Advance the alternate state sequence.
00E3AB  1               
00E3AB  1               ProcessCompactObjectState_Return: ; $E3AB
00E3AB  1  60               rts                         ; $E3AB: 60
00E3AC  1               
00E3AC  1               ; ============================================================================
00E3AC  1               ; $E3AC-$E3DB
00E3AC  1               ; Run the selected object's geometry and animation transition.
00E3AC  1               ;
00E3AC  1               ; The routine:
00E3AC  1               ;   1. Initializes geometry or object state through $E59D.
00E3AC  1               ;   2. Repeats the geometry test until it clears.
00E3AC  1               ;   3. Updates the current object's display state.
00E3AC  1               ;   4. Waits until the test at $E57E returns carry clear.
00E3AC  1               ;   5. Resets shared state and returns to the main object dispatcher.
00E3AC  1               ; ============================================================================
00E3AC  1               
00E3AC  1               RunSelectedObjectTransition:    ; $E3AC
00E3AC  1  20 9D E5         jsr InitializeSharedObjectMotion                   ; $E3AC: 20 9D E5
00E3AF  1               
00E3AF  1               ; ----------------------------------------------------------------------------
00E3AF  1               ; Prepare and test the current object's geometry.
00E3AF  1               ;
00E3AF  1               ; Carry set runs the animation-and-wait helper at $E313, then retries from
00E3AF  1               ; $E3AF. Carry clear continues with display-state processing.
00E3AF  1               ; ----------------------------------------------------------------------------
00E3AF  1               
00E3AF  1               RunSelectedObjectTransition_TestGeometry: ; $E3AF
00E3AF  1  20 74 E4         jsr SelectGeometryRecord_Default                   ; $E3AF: 20 74 E4
00E3B2  1  20 5F E5         jsr ApplyCurrentObjectGeometry                   ; $E3B2: 20 5F E5
00E3B5  1               
00E3B5  1  90 06            bcc RunSelectedObjectTransition_GeometryClear
00E3B7  1                                               ; $E3B5: 90 06
00E3B7  1               
00E3B7  1  20 13 E3         jsr UpdateCurrentObjectAnimationAndWait
00E3BA  1                                               ; $E3B7: 20 13 E3
00E3BA  1               
00E3BA  1  4C AF E3         jmp RunSelectedObjectTransition_TestGeometry
00E3BD  1                                               ; $E3BA: 4C AF E3
00E3BD  1               
00E3BD  1               ; ----------------------------------------------------------------------------
00E3BD  1               ; Geometry cleared. Update the current object's display state.
00E3BD  1               ; ----------------------------------------------------------------------------
00E3BD  1               
00E3BD  1               RunSelectedObjectTransition_GeometryClear: ; $E3BD
00E3BD  1  20 D4 DF         jsr UpdateCurrentObjectDisplayState
00E3C0  1                                               ; $E3BD: 20 D4 DF
00E3C0  1               
00E3C0  1               ; ----------------------------------------------------------------------------
00E3C0  1               ; Wait three ticks, then test the condition at $E57E.
00E3C0  1               ;
00E3C0  1               ; Carry set repeats the delay and test. Carry clear completes the transition.
00E3C0  1               ; ----------------------------------------------------------------------------
00E3C0  1               
00E3C0  1               RunSelectedObjectTransition_WaitLoop: ; $E3C0
00E3C0  1  A9 03            lda #$03                    ; $E3C0: A9 03
00E3C2  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $E3C2: 20 41 EB
00E3C5  1               
00E3C5  1  20 7E E5         jsr ApplyBaseObjectGeometry                   ; $E3C5: 20 7E E5
00E3C8  1  B0 F6            bcs RunSelectedObjectTransition_WaitLoop
00E3CA  1                                               ; $E3C8: B0 F6
00E3CA  1               
00E3CA  1               ; ----------------------------------------------------------------------------
00E3CA  1               ; Set the shared engine flags and clear the selector remapping state.
00E3CA  1               ; ----------------------------------------------------------------------------
00E3CA  1               
00E3CA  1  A9 20            lda #$20                    ; $E3CA: A9 20
00E3CC  1  85 FE            sta PendingAudioFlags             ; $E3CC: 85 FE
00E3CE  1               
00E3CE  1  A9 00            lda #$00                    ; $E3CE: A9 00
00E3D0  1  85 BB            sta $BB                     ; $E3D0: 85 BB
00E3D2  1               
00E3D2  1               ; ----------------------------------------------------------------------------
00E3D2  1               ; Derive the current selector through GetCurrentObjectSelectorAndState and save
00E3D2  1               ; it to both $9E and $C2.
00E3D2  1               ; ----------------------------------------------------------------------------
00E3D2  1               
00E3D2  1  20 DC E3         jsr GetCurrentObjectSelectorAndState
00E3D5  1                                               ; $E3D2: 20 DC E3
00E3D5  1               
00E3D5  1  84 9E            sty $9E                     ; $E3D5: 84 9E
00E3D7  1  84 C2            sty $C2                     ; $E3D7: 84 C2
00E3D9  1               
00E3D9  1               ; ----------------------------------------------------------------------------
00E3D9  1               ; Return to the main object-state dispatcher setup at $E040.
00E3D9  1               ; ----------------------------------------------------------------------------
00E3D9  1               
00E3D9  1  4C 40 E0         jmp ProcessObjectStateSelection                   ; $E3D9: 4C 40 E0
00E3DC  1               
00E3DC  1               ; ============================================================================
00E3DC  1               ; $E3DC-$E3E5
00E3DC  1               ; Derive the compact state index and saved selector for CurrentObjectIndex.
00E3DC  1               ;
00E3DC  1               ; Exit:
00E3DC  1               ;   X = CurrentObjectIndex
00E3DC  1               ;   Y = $0595[CurrentObjectIndex / 2]
00E3DC  1               ;   A = CurrentObjectIndex / 2
00E3DC  1               ;
00E3DC  1               ; The final LDX restores the full object-array offset in X while leaving the
00E3DC  1               ; compact index in A and the saved selector in Y.
00E3DC  1               ; ============================================================================
00E3DC  1               
00E3DC  1               ; ----------------------------------------------------------------------------
00E3DC  1               ; Contract:
00E3DC  1               ;   Description: Implements Get Current Object Selector And State.
00E3DC  1               ;   Entry: Registers: A; Memory: currentobjectindex, $0595
00E3DC  1               ;   Returns/products: Registers/clobbers: A, X, Y; Flags: condition flags may carry result state
00E3DC  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E3DC  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00E3DC  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E3DC  1               ;          comparison, load, or store path and are not a stable API product.
00E3DC  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 13.
00E3DC  1               ; ----------------------------------------------------------------------------
00E3DC  1               GetCurrentObjectSelectorAndState: ; $E3DC
00E3DC  1  A5 E1            lda CurrentObjectIndex      ; $E3DC: A5 E1
00E3DE  1  4A               lsr                         ; $E3DE: 4A
00E3DF  1  AA               tax                         ; $E3DF: AA
00E3E0  1               
00E3E0  1  BC 95 05         ldy $0595,x                 ; $E3E0: BC 95 05
00E3E3  1               
00E3E3  1  A6 E1            ldx CurrentObjectIndex      ; $E3E3: A6 E1
00E3E5  1  60               rts                         ; $E3E5: 60
00E3E6  1               
00E3E6  1               ; ============================================================================
00E3E6  1               ; $E3E6-$E412
00E3E6  1               ; Copy the current object's position into the base-object position fields,
00E3E6  1               ; initialize the base object's motion state, clear its auxiliary fields, and
00E3E6  1               ; save the result in BaseMotionActive.
00E3E6  1               ;
00E3E6  1               ; Entry:
00E3E6  1               ;   CurrentObjectIndex = source object-array offset
00E3E6  1               ;
00E3E6  1               ; Exit:
00E3E6  1               ;   A = value returned by ClearBaseAccelerationFields
00E3E6  1               ;   X = CurrentObjectIndex
00E3E6  1               ;   BaseMotionActive = returned value
00E3E6  1               ; ============================================================================
00E3E6  1               
00E3E6  1               ; ----------------------------------------------------------------------------
00E3E6  1               ; Contract:
00E3E6  1               ;   Description: Initializes Base Object From Current.
00E3E6  1               ;   Entry: Registers: A; Memory: currentobjectindex, $0509, $050a, $053a, $053b
00E3E6  1               ;   Returns/products: Registers/clobbers: A, X
00E3E6  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E3E6  1               ;   Memory effects: $0509, $050a, $053a, $053b, $056b, $056c, basemotionactive
00E3E6  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E3E6  1               ;          comparison, load, or store path and are not a stable API product.
00E3E6  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 6.
00E3E6  1               ; ----------------------------------------------------------------------------
00E3E6  1               InitializeBaseObjectFromCurrent: ; $E3E6
00E3E6  1  A6 E1            ldx CurrentObjectIndex      ; $E3E6: A6 E1
00E3E8  1               
00E3E8  1               ; ----------------------------------------------------------------------------
00E3E8  1               ; Copy the current object's horizontal coordinate to the base object.
00E3E8  1               ; ----------------------------------------------------------------------------
00E3E8  1               
00E3E8  1               ; ----------------------------------------------------------------------------
00E3E8  1               ; Contract:
00E3E8  1               ;   Description: Internal position-copy entry with X already loaded.
00E3E8  1               ;   Entry: X = current object array offset.
00E3E8  1               ;   Returns/products: Base object position fields updated.
00E3E8  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E3E8  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00E3E8  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E3E8  1               ;          comparison, load, or store path and are not a stable API product.
00E3E8  1               ;   Validation: Internal-entry contract; call sites: internal entry.
00E3E8  1               ; ----------------------------------------------------------------------------
00E3E8  1               CopyCurrentObjectPositionToBaseAfterIndex:
00E3E8  1  BD 09 05         lda $0509,x                 ; $E3E8: BD 09 05
00E3EB  1  8D 09 05         sta $0509                   ; $E3EB: 8D 09 05
00E3EE  1               
00E3EE  1  BD 0A 05         lda $050A,x                 ; $E3EE: BD 0A 05
00E3F1  1  8D 0A 05         sta $050A                   ; $E3F1: 8D 0A 05
00E3F4  1               
00E3F4  1               ; ----------------------------------------------------------------------------
00E3F4  1               ; Copy the current object's vertical coordinate to the base object.
00E3F4  1               ; ----------------------------------------------------------------------------
00E3F4  1               
00E3F4  1  BD 3A 05         lda $053A,x                 ; $E3F4: BD 3A 05
00E3F7  1  8D 3A 05         sta $053A                   ; $E3F7: 8D 3A 05
00E3FA  1               
00E3FA  1  BD 3B 05         lda $053B,x                 ; $E3FA: BD 3B 05
00E3FD  1  8D 3B 05         sta $053B                   ; $E3FD: 8D 3B 05
00E400  1               
00E400  1               ; ----------------------------------------------------------------------------
00E400  1               ; Initialize the base object's movement/state pair.
00E400  1               ; ----------------------------------------------------------------------------
00E400  1               
00E400  1  A9 00            lda #$00                    ; $E400: A9 00
00E402  1  8D 6B 05         sta $056B                   ; $E402: 8D 6B 05
00E405  1               
00E405  1  A9 01            lda #$01                    ; $E405: A9 01
00E407  1  8D 6C 05         sta $056C                   ; $E407: 8D 6C 05
00E40A  1               
00E40A  1               ; ----------------------------------------------------------------------------
00E40A  1               ; Clear the base object's position/motion fields.
00E40A  1               ;
00E40A  1               ; These calls use the earlier helpers at $C94F and ClearBaseAccelerationFields
00E40A  1               ; ----------------------------------------------------------------------------
00E40A  1               
00E40A  1  20 4F C9         jsr ClearBasePositionFields            ; $E40A: 20 4F C9
00E40D  1  20 43 C9         jsr ClearBaseAccelerationFields            ; $E40D: 20 43 C9
00E410  1               
00E410  1               ; ----------------------------------------------------------------------------
00E410  1               ; Save the result from ClearBaseAccelerationFields as the active-motion state.
00E410  1               ; ----------------------------------------------------------------------------
00E410  1               
00E410  1  85 5C            sta BaseMotionActive            ; $E410: 85 5C
00E412  1               
00E412  1  60               rts                         ; $E412: 60
00E413  1               
00E413  1               ; ============================================================================
00E413  1               ; $E413-$E432
00E413  1               ; Geometry parameter data, first 32 bytes.
00E413  1               ;
00E413  1               ; Keep this region as raw bytes. Later routines use calculated and overlapping
00E413  1               ; offsets into the larger data structure.
00E413  1               ; ============================================================================
00E413  1               
00E413  1               GeometryParameterData:          ; $E413
00E413  1  D0 05 00 00      .byte $D0,$05,$00,$00,$00,$02,$30,$08
00E417  1  00 02 30 08  
00E41B  1  20 F9 C0 00      .byte $20,$F9,$C0,$00,$00,$00,$40,$F7
00E41F  1  00 00 40 F7  
00E423  1  00 FE 00 FC      .byte $00,$FE,$00,$FC,$00,$02,$00,$04
00E427  1  00 02 00 04  
00E42B  1  80 06 00 00      .byte $80,$06,$00,$00,$D0,$00,$50,$08
00E42F  1  D0 00 50 08  
00E433  1               GeometryParameterData_Block2:   ; $E433
00E433  1  40 F8 C0 00      .byte $40,$F8,$C0,$00,$00,$00,$40,$F7
00E437  1  00 00 40 F7  
00E43B  1  00 08 00 00      .byte $00,$08,$00,$00,$00,$00,$00,$08
00E43F  1  00 00 00 08  
00E443  1  00 F8 00 00      .byte $00,$F8,$00,$00,$00,$00,$00,$F8
00E447  1  00 00 00 F8  
00E44B  1  00 07 80 00      .byte $00,$07,$80,$00,$00,$FF,$00,$08
00E44F  1  00 FF 00 08  
00E453  1               GeometryParameterData_Block3:   ; $E453
00E453  1  80 F8 80 FF      .byte $80,$F8,$80,$FF,$00,$03,$00,$F5
00E457  1  00 03 00 F5  
00E45B  1  A0 06 60 01      .byte $A0,$06,$60,$01,$40,$FE,$C0,$06
00E45F  1  40 FE C0 06  
00E463  1  40 F9 60 FE      .byte $40,$F9,$60,$FE,$80,$06,$80,$FE
00E467  1  80 06 80 FE  
00E46B  1               
00E46B  1               ; ============================================================================
00E46B  1               ; $E46B-$E473
00E46B  1               ; Convert the current object's saved selector into a four-byte geometry-record
00E46B  1               ; offset.
00E46B  1               ;
00E46B  1               ; GetCurrentObjectSelectorAndState returns the saved selector in Y.
00E46B  1               ;
00E46B  1               ; Exit:
00E46B  1               ;   Y = (saved selector - 1) * 4
00E46B  1               ; ============================================================================
00E46B  1               
00E46B  1               GetCurrentGeometryRecordOffset: ; $E46B
00E46B  1  20 DC E3         jsr GetCurrentObjectSelectorAndState
00E46E  1                                               ; $E46B: 20 DC E3
00E46E  1               
00E46E  1  88               dey                         ; $E46E: 88
00E46F  1  98               tya                         ; $E46F: 98
00E470  1               
00E470  1  0A               asl                         ; $E470: 0A
00E471  1  0A               asl                         ; $E471: 0A
00E472  1               
00E472  1  A8               tay                         ; $E472: A8
00E473  1  60               rts                         ; $E473: 60
00E474  1               
00E474  1               ; ============================================================================
00E474  1               ; $E474-$E4B7
00E474  1               ; Geometry-record selection helpers.
00E474  1               ;
00E474  1               ; Each entry selects:
00E474  1               ;
00E474  1               ;   Y = offset into the geometry data beginning at GeometryParameterData
00E474  1               ;   A = geometry parameter stored in $C6
00E474  1               ;
00E474  1               ; The entries at $E474 and $E481 preserve parameters $0F and $05 by branching
00E474  1               ; directly to STA $C6 at $E4B5.
00E474  1               ;
00E474  1               ; The remaining entries merge at $E4B2, convert their calculated offset from
00E474  1               ; A to Y, and use the default geometry parameter $07.
00E474  1               ; ============================================================================
00E474  1               
00E474  1               ; ----------------------------------------------------------------------------
00E474  1               ; Contract:
00E474  1               ;   Description: Implements Select Geometry Record  Default.
00E474  1               ;   Entry: Registers: A, Y
00E474  1               ;   Returns/products: Registers/clobbers: A, Y
00E474  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E474  1               ;   Memory effects: $c6
00E474  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E474  1               ;          comparison, load, or store path and are not a stable API product.
00E474  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 5.
00E474  1               ; ----------------------------------------------------------------------------
00E474  1               SelectGeometryRecord_Default:   ; $E474
00E474  1  20 DC E3         jsr GetCurrentObjectSelectorAndState
00E477  1                                               ; $E474: 20 DC E3
00E477  1               
00E477  1  98               tya                         ; $E477: 98
00E478  1  0A               asl                         ; $E478: 0A
00E479  1  0A               asl                         ; $E479: 0A
00E47A  1               
00E47A  1  69 14            adc #$14                    ; $E47A: 69 14
00E47C  1  A8               tay                         ; $E47C: A8
00E47D  1               
00E47D  1  A9 0F            lda #$0F                    ; $E47D: A9 0F
00E47F  1  D0 34            bne StoreGeometryParameter  ; $E47F: D0 34
00E481  1                                               ; Always taken.
00E481  1                                               ; Target $E4B5.
00E481  1               
00E481  1               ; ----------------------------------------------------------------------------
00E481  1               ; Select from the geometry-record group beginning at offset $44.
00E481  1               ;
00E481  1               ; Return:
00E481  1               ;   Y = (($selector << 1) & $0C) + $44
00E481  1               ;   $C6 = $05
00E481  1               ; ----------------------------------------------------------------------------
00E481  1               
00E481  1               ; ----------------------------------------------------------------------------
00E481  1               ; Contract:
00E481  1               ;   Description: Implements Select Geometry Record  4 4.
00E481  1               ;   Entry: Registers: A, Y
00E481  1               ;   Returns/products: Registers/clobbers: A, Y
00E481  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E481  1               ;   Memory effects: $c6
00E481  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E481  1               ;          comparison, load, or store path and are not a stable API product.
00E481  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00E481  1               ; ----------------------------------------------------------------------------
00E481  1               SelectGeometryRecord_44:        ; $E481
00E481  1  20 DC E3         jsr GetCurrentObjectSelectorAndState
00E484  1                                               ; $E481: 20 DC E3
00E484  1               
00E484  1  98               tya                         ; $E484: 98
00E485  1  0A               asl                         ; $E485: 0A
00E486  1  29 0C            and #$0C                    ; $E486: 29 0C
00E488  1               
00E488  1  69 44            adc #$44                    ; $E488: 69 44
00E48A  1  A8               tay                         ; $E48A: A8
00E48B  1               
00E48B  1  A9 05            lda #$05                    ; $E48B: A9 05
00E48D  1  D0 26            bne StoreGeometryParameter  ; $E48D: D0 26
00E48F  1                                               ; Always taken.
00E48F  1                                               ; Target $E4B5.
00E48F  1               
00E48F  1               ; ----------------------------------------------------------------------------
00E48F  1               ; Select from the geometry-record group beginning at offset $34.
00E48F  1               ;
00E48F  1               ; Return:
00E48F  1               ;   Y = (($selector << 1) & $1C) + $34
00E48F  1               ;   $C6 = $07
00E48F  1               ; ----------------------------------------------------------------------------
00E48F  1               
00E48F  1               ; ----------------------------------------------------------------------------
00E48F  1               ; Contract:
00E48F  1               ;   Description: Implements Select Geometry Record  3 4.
00E48F  1               ;   Entry: Registers: A, Y
00E48F  1               ;   Returns/products: Registers/clobbers: A, Y
00E48F  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E48F  1               ;   Memory effects: $c6
00E48F  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E48F  1               ;          comparison, load, or store path and are not a stable API product.
00E48F  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 3.
00E48F  1               ; ----------------------------------------------------------------------------
00E48F  1               SelectGeometryRecord_34:        ; $E48F
00E48F  1  20 DC E3         jsr GetCurrentObjectSelectorAndState
00E492  1                                               ; $E48F: 20 DC E3
00E492  1               
00E492  1  98               tya                         ; $E492: 98
00E493  1  0A               asl                         ; $E493: 0A
00E494  1  29 1C            and #$1C                    ; $E494: 29 1C
00E496  1               
00E496  1  69 34            adc #$34                    ; $E496: 69 34
00E498  1  D0 18            bne UseGeometryRecordOffset ; $E498: D0 18
00E49A  1                                               ; Target $E4B2.
00E49A  1               
00E49A  1               ; ----------------------------------------------------------------------------
00E49A  1               ; Select from the geometry-record group beginning at offset $28.
00E49A  1               ;
00E49A  1               ; Return:
00E49A  1               ;   Y = (($selector << 1) & $0C) + $28
00E49A  1               ;   $C6 = $07
00E49A  1               ; ----------------------------------------------------------------------------
00E49A  1               
00E49A  1               ; ----------------------------------------------------------------------------
00E49A  1               ; Contract:
00E49A  1               ;   Description: Implements Select Geometry Record  2 8.
00E49A  1               ;   Entry: Registers: A, Y
00E49A  1               ;   Returns/products: Registers/clobbers: A, Y
00E49A  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E49A  1               ;   Memory effects: $c6
00E49A  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E49A  1               ;          comparison, load, or store path and are not a stable API product.
00E49A  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00E49A  1               ; ----------------------------------------------------------------------------
00E49A  1               SelectGeometryRecord_28:        ; $E49A
00E49A  1  20 DC E3         jsr GetCurrentObjectSelectorAndState
00E49D  1                                               ; $E49A: 20 DC E3
00E49D  1               
00E49D  1  98               tya                         ; $E49D: 98
00E49E  1  0A               asl                         ; $E49E: 0A
00E49F  1  29 0C            and #$0C                    ; $E49F: 29 0C
00E4A1  1               
00E4A1  1  69 28            adc #$28                    ; $E4A1: 69 28
00E4A3  1  D0 0D            bne UseGeometryRecordOffset ; $E4A3: D0 0D
00E4A5  1                                               ; Target $E4B2.
00E4A5  1               
00E4A5  1               ; ----------------------------------------------------------------------------
00E4A5  1               ; Select from the geometry-record group beginning at offset $24.
00E4A5  1               ;
00E4A5  1               ; If the calculation produces zero, substitute fixed offset $54.
00E4A5  1               ;
00E4A5  1               ; Return:
00E4A5  1               ;   Y = calculated offset or $54
00E4A5  1               ;   $C6 = $07
00E4A5  1               ; ----------------------------------------------------------------------------
00E4A5  1               
00E4A5  1               ; ----------------------------------------------------------------------------
00E4A5  1               ; Contract:
00E4A5  1               ;   Description: Implements Select Geometry Record  2 4.
00E4A5  1               ;   Entry: Registers: A, Y
00E4A5  1               ;   Returns/products: Registers/clobbers: A, Y
00E4A5  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E4A5  1               ;   Memory effects: $c6
00E4A5  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E4A5  1               ;          comparison, load, or store path and are not a stable API product.
00E4A5  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00E4A5  1               ; ----------------------------------------------------------------------------
00E4A5  1               SelectGeometryRecord_24:        ; $E4A5
00E4A5  1  20 DC E3         jsr GetCurrentObjectSelectorAndState
00E4A8  1                                               ; $E4A5: 20 DC E3
00E4A8  1               
00E4A8  1  98               tya                         ; $E4A8: 98
00E4A9  1  0A               asl                         ; $E4A9: 0A
00E4AA  1  29 0C            and #$0C                    ; $E4AA: 29 0C
00E4AC  1               
00E4AC  1  69 24            adc #$24                    ; $E4AC: 69 24
00E4AE  1  D0 02            bne UseGeometryRecordOffset ; $E4AE: D0 02
00E4B0  1                                               ; Target $E4B2.
00E4B0  1               
00E4B0  1               ; ----------------------------------------------------------------------------
00E4B0  1               ; Contract:
00E4B0  1               ;   Description: Internal geometry-selector path using fixed record offset $54.
00E4B0  1               ;   Entry: No additional register input beyond parent selector state.
00E4B0  1               ;   Returns/products: Y receives record offset; shared geometry parameter set.
00E4B0  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E4B0  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00E4B0  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E4B0  1               ;          comparison, load, or store path and are not a stable API product.
00E4B0  1               ;   Validation: Internal-entry contract; call sites: internal entry.
00E4B0  1               ; ----------------------------------------------------------------------------
00E4B0  1               UseFixedGeometryRecord54:
00E4B0  1  A9 54            lda #$54                    ; $E4B0: A9 54
00E4B2  1               
00E4B2  1               ; ----------------------------------------------------------------------------
00E4B2  1               ; Convert the selected geometry-record offset from A to Y.
00E4B2  1               ; ----------------------------------------------------------------------------
00E4B2  1               
00E4B2  1               UseGeometryRecordOffset:        ; $E4B2
00E4B2  1  A8               tay                         ; $E4B2: A8
00E4B3  1               
00E4B3  1  A9 07            lda #$07                    ; $E4B3: A9 07
00E4B5  1               
00E4B5  1               ; ----------------------------------------------------------------------------
00E4B5  1               ; Shared parameter store.
00E4B5  1               ;
00E4B5  1               ; The branches from $E47F and $E48D enter directly here, preserving their
00E4B5  1               ; respective values $0F and $05.
00E4B5  1               ; ----------------------------------------------------------------------------
00E4B5  1               
00E4B5  1               StoreGeometryParameter:         ; $E4B5
00E4B5  1  85 C6            sta $C6                     ; $E4B5: 85 C6
00E4B7  1               
00E4B7  1  60               rts                         ; $E4B7: 60
00E4B8  1               
00E4B8  1               ; ============================================================================
00E4B8  1               ; $E4B8-$E4C1
00E4B8  1               ; Select a geometry record directly from CurrentObjectIndex.
00E4B8  1               ;
00E4B8  1               ; Return:
00E4B8  1               ;   Y = (CurrentObjectIndex * 2) + $F4
00E4B8  1               ;   $C6 = $0F
00E4B8  1               ;
00E4B8  1               ; The BNE branches backward directly to STA $C6 at $E4B5.
00E4B8  1               ; ============================================================================
00E4B8  1               
00E4B8  1               ; ----------------------------------------------------------------------------
00E4B8  1               ; Contract:
00E4B8  1               ;   Description: Implements Select Geometry Record From Object.
00E4B8  1               ;   Entry: Registers: A; Memory: currentobjectindex, GeometryParameterData, $e414, $e415, $e416
00E4B8  1               ;   Returns/products: Registers/clobbers: A, Y
00E4B8  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E4B8  1               ;   Memory effects: $b2, $b3, $b4, $b5
00E4B8  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E4B8  1               ;          comparison, load, or store path and are not a stable API product.
00E4B8  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00E4B8  1               ; ----------------------------------------------------------------------------
00E4B8  1               SelectGeometryRecordFromObject: ; $E4B8
00E4B8  1  A5 E1            lda CurrentObjectIndex      ; $E4B8: A5 E1
00E4BA  1  0A               asl                         ; $E4BA: 0A
00E4BB  1               
00E4BB  1  69 F4            adc #$F4                    ; $E4BB: 69 F4
00E4BD  1  A8               tay                         ; $E4BD: A8
00E4BE  1               
00E4BE  1  A9 0F            lda #$0F                    ; $E4BE: A9 0F
00E4C0  1  D0 F3            bne StoreGeometryParameter  ; $E4C0: D0 F3
00E4C2  1                                               ; Always taken.
00E4C2  1                                               ; Target $E4B5.
00E4C2  1               
00E4C2  1               ; ============================================================================
00E4C2  1               ; $E4C2-$E4D6
00E4C2  1               ; Load a four-byte geometry record into $B2-$B5.
00E4C2  1               ;
00E4C2  1               ; Entry:
00E4C2  1               ;   Y = byte offset into the geometry data beginning at GeometryParameterData
00E4C2  1               ;
00E4C2  1               ; Exit:
00E4C2  1               ;   $B2 = byte at $E413+Y
00E4C2  1               ;   $B3 = byte at $E414+Y
00E4C2  1               ;   $B4 = byte at $E415+Y
00E4C2  1               ;   $B5 = byte at $E416+Y
00E4C2  1               ;
00E4C2  1               ; Literal addresses are used because the geometry data was decoded as several
00E4C2  1               ; smaller source blocks.
00E4C2  1               ; ============================================================================
00E4C2  1               
00E4C2  1               ; ----------------------------------------------------------------------------
00E4C2  1               ; Contract:
00E4C2  1               ;   Description: Implements Load Geometry Record.
00E4C2  1               ;   Entry: Registers: A; Memory: GeometryParameterData, $e414, $e415, $e416
00E4C2  1               ;   Returns/products: Registers/clobbers: A
00E4C2  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E4C2  1               ;   Memory effects: $b2, $b3, $b4, $b5
00E4C2  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E4C2  1               ;          comparison, load, or store path and are not a stable API product.
00E4C2  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 6.
00E4C2  1               ; ----------------------------------------------------------------------------
00E4C2  1               LoadGeometryRecord:             ; $E4C2
00E4C2  1  B9 13 E4         lda GeometryParameterData,y                 ; $E4C2: B9 13 E4
00E4C5  1  85 B2            sta $B2                     ; $E4C5: 85 B2
00E4C7  1               
00E4C7  1  B9 14 E4         lda GeometryParameterData+1,y                 ; $E4C7: B9 14 E4
00E4CA  1  85 B3            sta $B3                     ; $E4CA: 85 B3
00E4CC  1               
00E4CC  1  B9 15 E4         lda GeometryParameterData+2,y                 ; $E4CC: B9 15 E4
00E4CF  1  85 B4            sta $B4                     ; $E4CF: 85 B4
00E4D1  1               
00E4D1  1  B9 16 E4         lda GeometryParameterData+3,y                 ; $E4D1: B9 16 E4
00E4D4  1  85 B5            sta $B5                     ; $E4D4: 85 B5
00E4D6  1               
00E4D6  1  60               rts                         ; $E4D6: 60
00E4D7  1               
00E4D7  1               ; ============================================================================
00E4D7  1               ; $E4D7-$E501
00E4D7  1               ; Calculate doubled signed coordinate differences between geometry arguments
00E4D7  1               ; $B2-$B5 and an object position.
00E4D7  1               ;
00E4D7  1               ; Two entry points select the object:
00E4D7  1               ;
00E4D7  1               ;   $E4D7: compare against the base object at array offset $00
00E4D7  1               ;   $E4DB: compare against CurrentObjectIndex
00E4D7  1               ;
00E4D7  1               ; Results:
00E4D7  1               ;   $AE/$AF = doubled horizontal difference
00E4D7  1               ;   $B0/$B1 = doubled vertical difference
00E4D7  1               ; ============================================================================
00E4D7  1               
00E4D7  1               CalculateBaseGeometryDifference: ; $E4D7
00E4D7  1  A2 00            ldx #$00                    ; $E4D7: A2 00
00E4D9  1  F0 02            beq CalculateGeometryDifference
00E4DB  1                                               ; $E4D9: F0 02
00E4DB  1                                               ; Always taken because X is zero.
00E4DB  1               
00E4DB  1               ; ----------------------------------------------------------------------------
00E4DB  1               ; Contract:
00E4DB  1               ;   Description: Calculates Current Geometry Difference.
00E4DB  1               ;   Entry: Registers: A; Memory: currentobjectindex, $b2, $0509, $b3, $050a, $b4, $053a, $b5
00E4DB  1               ;   Returns/products: Registers/clobbers: A, X
00E4DB  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E4DB  1               ;   Memory effects: calculatedcoordinatelow, calculatedcoordinatehigh, $b0, $b1
00E4DB  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E4DB  1               ;          comparison, load, or store path and are not a stable API product.
00E4DB  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 5.
00E4DB  1               ; ----------------------------------------------------------------------------
00E4DB  1               CalculateCurrentGeometryDifference: ; $E4DB
00E4DB  1  A6 E1            ldx CurrentObjectIndex      ; $E4DB: A6 E1
00E4DD  1               
00E4DD  1               ; ----------------------------------------------------------------------------
00E4DD  1               ; Calculate the signed horizontal difference:
00E4DD  1               ;
00E4DD  1               ;   ($B2/$B3) - ($0509/$050A,X)
00E4DD  1               ;
00E4DD  1               ; Then multiply the 16-bit result by two.
00E4DD  1               ; ----------------------------------------------------------------------------
00E4DD  1               
00E4DD  1               ; ----------------------------------------------------------------------------
00E4DD  1               ; Contract:
00E4DD  1               ;   Description: Calculates Geometry Difference.
00E4DD  1               ;   Entry: Registers: A; Memory: $b2, $0509, $b3, $050a, $b4, $053a, $b5, $053b
00E4DD  1               ;   Returns/products: Registers/clobbers: A
00E4DD  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E4DD  1               ;   Memory effects: calculatedcoordinatelow, calculatedcoordinatehigh, $b0, $b1
00E4DD  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E4DD  1               ;          comparison, load, or store path and are not a stable API product.
00E4DD  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00E4DD  1               ; ----------------------------------------------------------------------------
00E4DD  1               CalculateGeometryDifference:    ; $E4DD
00E4DD  1  38               sec                         ; $E4DD: 38
00E4DE  1               
00E4DE  1  A5 B2            lda $B2                     ; $E4DE: A5 B2
00E4E0  1  FD 09 05         sbc $0509,x                 ; $E4E0: FD 09 05
00E4E3  1  85 AE            sta CalculatedCoordinateLow        ; $E4E3: 85 AE
00E4E5  1               
00E4E5  1  A5 B3            lda $B3                     ; $E4E5: A5 B3
00E4E7  1  FD 0A 05         sbc $050A,x                 ; $E4E7: FD 0A 05
00E4EA  1               
00E4EA  1  06 AE            asl CalculatedCoordinateLow        ; $E4EA: 06 AE
00E4EC  1  2A               rol                         ; $E4EC: 2A
00E4ED  1  85 AF            sta CalculatedCoordinateHigh        ; $E4ED: 85 AF
00E4EF  1               
00E4EF  1               ; ----------------------------------------------------------------------------
00E4EF  1               ; Calculate the signed vertical difference:
00E4EF  1               ;
00E4EF  1               ;   ($B4/$B5) - ($053A/$053B,X)
00E4EF  1               ;
00E4EF  1               ; Then multiply the 16-bit result by two.
00E4EF  1               ; ----------------------------------------------------------------------------
00E4EF  1               
00E4EF  1  38               sec                         ; $E4EF: 38
00E4F0  1               
00E4F0  1  A5 B4            lda $B4                     ; $E4F0: A5 B4
00E4F2  1  FD 3A 05         sbc $053A,x                 ; $E4F2: FD 3A 05
00E4F5  1  85 B0            sta $B0                     ; $E4F5: 85 B0
00E4F7  1               
00E4F7  1  A5 B5            lda $B5                     ; $E4F7: A5 B5
00E4F9  1  FD 3B 05         sbc $053B,x                 ; $E4F9: FD 3B 05
00E4FC  1               
00E4FC  1  06 B0            asl $B0                     ; $E4FC: 06 B0
00E4FE  1  2A               rol                         ; $E4FE: 2A
00E4FF  1  85 B1            sta $B1                     ; $E4FF: 85 B1
00E501  1               
00E501  1  60               rts                         ; $E501: 60
00E502  1               
00E502  1               ; ============================================================================
00E502  1               ; $E502-$E512
00E502  1               ; Normalize or measure the signed coordinate difference in $AE-$B1.
00E502  1               ;
00E502  1               ; The high bytes are adjusted upward when the corresponding low signed value
00E502  1               ; is negative, then passed to the vector or distance helper at $E80B.
00E502  1               ;
00E502  1               ; Entry:
00E502  1               ;   $AE/$AF = signed horizontal difference
00E502  1               ;   $B0/$B1 = signed vertical difference
00E502  1               ;
00E502  1               ; Exit:
00E502  1               ;   Returned directly from $E80B
00E502  1               ; ============================================================================
00E502  1               
00E502  1               ; ----------------------------------------------------------------------------
00E502  1               ; Contract:
00E502  1               ;   Description: Implements Evaluate Geometry Difference.
00E502  1               ;   Entry: Registers: X, Y; Memory: calculatedcoordinatehigh, calculatedcoordinatelow, $b1, $b0
00E502  1               ;   Returns/products: Registers/clobbers: A, X, Y
00E502  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E502  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00E502  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E502  1               ;          comparison, load, or store path and are not a stable API product.
00E502  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 5.
00E502  1               ; ----------------------------------------------------------------------------
00E502  1               EvaluateGeometryDifference:     ; $E502
00E502  1  A6 AF            ldx CalculatedCoordinateHigh        ; $E502: A6 AF
00E504  1               
00E504  1  A5 AE            lda CalculatedCoordinateLow        ; $E504: A5 AE
00E506  1  10 01            bpl EvaluateGeometryDifference_HorizontalReady
00E508  1                                               ; $E506: 10 01
00E508  1               
00E508  1  E8               inx                         ; $E508: E8
00E509  1               
00E509  1               EvaluateGeometryDifference_HorizontalReady: ; $E509
00E509  1  A4 B1            ldy $B1                     ; $E509: A4 B1
00E50B  1               
00E50B  1  A5 B0            lda $B0                     ; $E50B: A5 B0
00E50D  1  10 01            bpl EvaluateGeometryDifference_VerticalReady
00E50F  1                                               ; $E50D: 10 01
00E50F  1               
00E50F  1  C8               iny                         ; $E50F: C8
00E510  1               
00E510  1               EvaluateGeometryDifference_VerticalReady: ; $E510
00E510  1  4C 0B E8         jmp CalculateVectorMagnitude                   ; $E510: 4C 0B E8
00E513  1               
00E513  1               ; ============================================================================
00E513  1               ; $E513-$E527
00E513  1               ; Convert geometry parameter bytes into a signed vector.
00E513  1               ;
00E513  1               ; Entry:
00E513  1               ;   A = horizontal parameter
00E513  1               ;   $B5 = vertical parameter or zero
00E513  1               ;   $AF/$B1 = signed coordinate-difference high bytes
00E513  1               ;
00E513  1               ; Operation:
00E513  1               ;   1. Save A in $B3.
00E513  1               ;   2. Clear $B5.
00E513  1               ;   3. Copy $B3/$B5 into $D6/$D7.
00E513  1               ;   4. Pass X=$AF and Y=$B1 to $E828.
00E513  1               ;
00E513  1               ; Exit:
00E513  1               ;   Returned directly from $E828
00E513  1               ; ============================================================================
00E513  1               
00E513  1               ; ----------------------------------------------------------------------------
00E513  1               ; Contract:
00E513  1               ;   Description: Implements Build Geometry Vector.
00E513  1               ;   Entry: Registers: A; Memory: $b3, $b5, calculatedcoordinatehigh, $b1
00E513  1               ;   Returns/products: Registers/clobbers: A, X, Y
00E513  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E513  1               ;   Memory effects: $b3, $b5, $d6, $d7
00E513  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E513  1               ;          comparison, load, or store path and are not a stable API product.
00E513  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 5.
00E513  1               ; ----------------------------------------------------------------------------
00E513  1               BuildGeometryVector:            ; $E513
00E513  1  85 B3            sta $B3                     ; $E513: 85 B3
00E515  1               
00E515  1  A9 00            lda #$00                    ; $E515: A9 00
00E517  1  85 B5            sta $B5                     ; $E517: 85 B5
00E519  1               
00E519  1               ; ----------------------------------------------------------------------------
00E519  1               ; Alternate entry used when $B3 and $B5 are already initialized.
00E519  1               ; ----------------------------------------------------------------------------
00E519  1               
00E519  1               ; ----------------------------------------------------------------------------
00E519  1               ; Contract:
00E519  1               ;   Description: Implements Build Geometry Vector From Arguments.
00E519  1               ;   Entry: Registers: A; Memory: $b3, $b5, calculatedcoordinatehigh, $b1
00E519  1               ;   Returns/products: Registers/clobbers: A, X, Y
00E519  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E519  1               ;   Memory effects: $d6, $d7
00E519  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E519  1               ;          comparison, load, or store path and are not a stable API product.
00E519  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 2.
00E519  1               ; ----------------------------------------------------------------------------
00E519  1               BuildGeometryVectorFromArguments: ; $E519
00E519  1  A5 B3            lda $B3                     ; $E519: A5 B3
00E51B  1  85 D6            sta $D6                     ; $E51B: 85 D6
00E51D  1               
00E51D  1  A5 B5            lda $B5                     ; $E51D: A5 B5
00E51F  1  85 D7            sta $D7                     ; $E51F: 85 D7
00E521  1               
00E521  1  A6 AF            ldx CalculatedCoordinateHigh        ; $E521: A6 AF
00E523  1  A4 B1            ldy $B1                     ; $E523: A4 B1
00E525  1               
00E525  1  4C 28 E8         jmp CalculateSignedVectorFromResult                   ; $E525: 4C 28 E8
00E528  1               
00E528  1               ; ============================================================================
00E528  1               ; $E528-$E532
00E528  1               ; Store a calculated movement vector into the current object.
00E528  1               ;
00E528  1               ; Entry:
00E528  1               ;   A = horizontal movement low/result byte
00E528  1               ;   Y = vertical movement low/result byte
00E528  1               ;
00E528  1               ; Exit:
00E528  1               ;   X = CurrentObjectIndex
00E528  1               ;
00E528  1               ; Modified fields:
00E528  1               ;   $056D,X = A
00E528  1               ;   $056E,X = Y
00E528  1               ; ============================================================================
00E528  1               
00E528  1               ; ----------------------------------------------------------------------------
00E528  1               ; Contract:
00E528  1               ;   Description: Implements Store Current Object Movement.
00E528  1               ;   Entry: Registers: A, Y; Memory: currentobjectindex
00E528  1               ;   Returns/products: Registers/clobbers: A, X
00E528  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E528  1               ;   Memory effects: $056d, $056e
00E528  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E528  1               ;          comparison, load, or store path and are not a stable API product.
00E528  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 4.
00E528  1               ; ----------------------------------------------------------------------------
00E528  1               StoreCurrentObjectMovement:     ; $E528
00E528  1  AA               tax                         ; $E528: AA
00E529  1                                               ; Temporarily preserve A in X.
00E529  1               
00E529  1  A6 E1            ldx CurrentObjectIndex      ; $E529: A6 E1
00E52B  1               
00E52B  1  9D 6D 05         sta $056D,x                 ; $E52B: 9D 6D 05
00E52E  1               
00E52E  1  98               tya                         ; $E52E: 98
00E52F  1  9D 6E 05         sta $056E,x                 ; $E52F: 9D 6E 05
00E532  1               
00E532  1  60               rts                         ; $E532: 60
00E533  1               
00E533  1               ; ============================================================================
00E533  1               ; $E533-$E547
00E533  1               ; Store a calculated position in the base object and clear its movement fields.
00E533  1               ;
00E533  1               ; Entry:
00E533  1               ;   A = horizontal low/result byte
00E533  1               ;   Y = vertical low/result byte
00E533  1               ;
00E533  1               ; Modified fields:
00E533  1               ;   $0508 = A
00E533  1               ;   $0539 = Y
00E533  1               ;
00E533  1               ;   $056A = $00
00E533  1               ;   $0507 = $00
00E533  1               ;   $0538 = $00
00E533  1               ;   $0569 = $00
00E533  1               ;
00E533  1               ; Exit:
00E533  1               ;   A = $00
00E533  1               ; ============================================================================
00E533  1               
00E533  1               StoreBaseObjectPositionAndClearMovement: ; $E533
00E533  1  8D 08 05         sta $0508                   ; $E533: 8D 08 05
00E536  1  8C 39 05         sty $0539                   ; $E536: 8C 39 05
00E539  1               
00E539  1               ; ----------------------------------------------------------------------------
00E539  1               ; Clear the remaining base-object movement components.
00E539  1               ; ----------------------------------------------------------------------------
00E539  1               
00E539  1  A9 00            lda #$00                    ; $E539: A9 00
00E53B  1               
00E53B  1  8D 6A 05         sta $056A                   ; $E53B: 8D 6A 05
00E53E  1  8D 07 05         sta $0507                   ; $E53E: 8D 07 05
00E541  1  8D 38 05         sta $0538                   ; $E541: 8D 38 05
00E544  1  8D 69 05         sta $0569                   ; $E544: 8D 69 05
00E547  1               
00E547  1  60               rts                         ; $E547: 60
00E548  1               
00E548  1               ; ============================================================================
00E548  1               ; $E548-$E54E
00E548  1               ; Begin copying geometry arguments into the current object's coordinates.
00E548  1               ; ============================================================================
00E548  1               
00E548  1               ; ----------------------------------------------------------------------------
00E548  1               ; Contract:
00E548  1               ;   Description: Implements Store Geometry In Current Object.
00E548  1               ;   Entry: Registers: A; Memory: currentobjectindex, $b2, $b3, $b4, $b5
00E548  1               ;   Returns/products: Registers/clobbers: A, X
00E548  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E548  1               ;   Memory effects: $0509, $050a, $053a, $053b
00E548  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E548  1               ;          comparison, load, or store path and are not a stable API product.
00E548  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00E548  1               ; ----------------------------------------------------------------------------
00E548  1               StoreGeometryInCurrentObject:   ; $E548
00E548  1  A6 E1            ldx CurrentObjectIndex      ; $E548: A6 E1
00E54A  1               
00E54A  1  A5 B2            lda $B2                     ; $E54A: A5 B2
00E54C  1  9D 09 05         sta $0509,x                 ; $E54C: 9D 09 05
00E54F  1               
00E54F  1               ; ============================================================================
00E54F  1               ; $E54F-$E561
00E54F  1               ; Complete the copy of geometry arguments $B2-$B5 into the current object's
00E54F  1               ; coordinate fields.
00E54F  1               ;
00E54F  1               ; Entry:
00E54F  1               ;   X = CurrentObjectIndex, loaded by the preceding code at $E548
00E54F  1               ;
00E54F  1               ; Geometry source:
00E54F  1               ;   $B2 = horizontal low byte
00E54F  1               ;   $B3 = horizontal high byte
00E54F  1               ;   $B4 = vertical low byte
00E54F  1               ;   $B5 = vertical high byte
00E54F  1               ;
00E54F  1               ; Object destination:
00E54F  1               ;   $0509,X/$050A,X = horizontal coordinate
00E54F  1               ;   $053A,X/$053B,X = vertical coordinate
00E54F  1               ; ============================================================================
00E54F  1               
00E54F  1  A5 B3            lda $B3                     ; $E54F: A5 B3
00E551  1  9D 0A 05         sta $050A,x                 ; $E551: 9D 0A 05
00E554  1               
00E554  1  A5 B4            lda $B4                     ; $E554: A5 B4
00E556  1  9D 3A 05         sta $053A,x                 ; $E556: 9D 3A 05
00E559  1               
00E559  1  A5 B5            lda $B5                     ; $E559: A5 B5
00E55B  1  9D 3B 05         sta $053B,x                 ; $E55B: 9D 3B 05
00E55E  1               
00E55E  1  60               rts                         ; $E55E: 60
00E55F  1               
00E55F  1               ; ============================================================================
00E55F  1               ; $E55F-$E57D
00E55F  1               ; Load the selected geometry record, compare it with the current object, and
00E55F  1               ; either apply a calculated movement vector or copy the geometry directly into
00E55F  1               ; the current object's position.
00E55F  1               ;
00E55F  1               ; Entry:
00E55F  1               ;   Y   = geometry-record offset
00E55F  1               ;   $C6 = geometry/vector parameter
00E55F  1               ;
00E55F  1               ; Return:
00E55F  1               ;   C = set when the geometry result is at least $02
00E55F  1               ;   C = clear when the geometry result is below $02
00E55F  1               ; ============================================================================
00E55F  1               
00E55F  1               ; ----------------------------------------------------------------------------
00E55F  1               ; Contract:
00E55F  1               ;   Description: Implements Apply Current Object Geometry.
00E55F  1               ;   Entry: Registers: A; Memory: $c6
00E55F  1               ;   Returns/products: Registers/clobbers: A; Flags: condition flags may carry result state
00E55F  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E55F  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00E55F  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E55F  1               ;          comparison, load, or store path and are not a stable API product.
00E55F  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 11.
00E55F  1               ; ----------------------------------------------------------------------------
00E55F  1               ApplyCurrentObjectGeometry:     ; $E55F
00E55F  1  20 C2 E4         jsr LoadGeometryRecord      ; $E55F: 20 C2 E4
00E562  1               
00E562  1               ; ----------------------------------------------------------------------------
00E562  1               ; Calculate and evaluate the difference between the loaded geometry record
00E562  1               ; and the current object.
00E562  1               ; ----------------------------------------------------------------------------
00E562  1               EvaluateLoadedCurrentObjectGeometry:
00E562  1  20 DB E4         jsr CalculateCurrentGeometryDifference
00E565  1                                               ; $E562: 20 DB E4
00E565  1               
00E565  1  20 02 E5         jsr EvaluateGeometryDifference
00E568  1                                               ; $E565: 20 02 E5
00E568  1               
00E568  1  C9 02            cmp #$02                    ; $E568: C9 02
00E56A  1  90 0A            bcc ApplyCurrentObjectGeometry_CopyPosition
00E56C  1                                               ; $E56A: 90 0A
00E56C  1               
00E56C  1               ; ----------------------------------------------------------------------------
00E56C  1               ; Geometry result is at least two.
00E56C  1               ;
00E56C  1               ; Use the selected parameter in $C6 to build a movement vector and store it in
00E56C  1               ; the current object's movement fields.
00E56C  1               ; ----------------------------------------------------------------------------
00E56C  1               
00E56C  1  A5 C6            lda $C6                     ; $E56C: A5 C6
00E56E  1               
00E56E  1  20 13 E5         jsr BuildGeometryVector     ; $E56E: 20 13 E5
00E571  1  20 28 E5         jsr StoreCurrentObjectMovement
00E574  1                                               ; $E571: 20 28 E5
00E574  1               
00E574  1  38               sec                         ; $E574: 38
00E575  1  60               rts                         ; $E575: 60
00E576  1               
00E576  1               ; ----------------------------------------------------------------------------
00E576  1               ; Geometry result is below two.
00E576  1               ;
00E576  1               ; Copy the loaded geometry record directly into the current object's position,
00E576  1               ; clear the object's movement fields, and return carry clear.
00E576  1               ; ----------------------------------------------------------------------------
00E576  1               
00E576  1               ApplyCurrentObjectGeometry_CopyPosition: ; $E576
00E576  1  20 48 E5         jsr StoreGeometryInCurrentObject
00E579  1                                               ; $E576: 20 48 E5
00E579  1               
00E579  1  20 D3 E2         jsr ClearCurrentObjectMovement
00E57C  1                                               ; $E579: 20 D3 E2
00E57C  1               
00E57C  1  18               clc                         ; $E57C: 18
00E57D  1  60               rts                         ; $E57D: 60
00E57E  1               
00E57E  1               ; ============================================================================
00E57E  1               ; $E57E-$E59C
00E57E  1               ; Select a geometry record from the current object's saved selector, compare
00E57E  1               ; it with the base object, and either update the base object's movement or
00E57E  1               ; initialize the base object from the current object.
00E57E  1               ;
00E57E  1               ; Entry:
00E57E  1               ;   CurrentObjectIndex selects the current object.
00E57E  1               ;
00E57E  1               ; Return:
00E57E  1               ;   C = set when the geometry result is at least $02
00E57E  1               ;   C = clear when the geometry result is below $02
00E57E  1               ; ============================================================================
00E57E  1               
00E57E  1               ; ----------------------------------------------------------------------------
00E57E  1               ; Contract:
00E57E  1               ;   Description: Implements Apply Base Object Geometry.
00E57E  1               ;   Entry: Registers: A; Memory: $c5
00E57E  1               ;   Returns/products: Registers/clobbers: A; Flags: condition flags may carry result state
00E57E  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E57E  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00E57E  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E57E  1               ;          comparison, load, or store path and are not a stable API product.
00E57E  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00E57E  1               ; ----------------------------------------------------------------------------
00E57E  1               ApplyBaseObjectGeometry:        ; $E57E
00E57E  1  20 6B E4         jsr GetCurrentGeometryRecordOffset
00E581  1                                               ; $E57E: 20 6B E4
00E581  1               
00E581  1  20 C2 E4         jsr LoadGeometryRecord      ; $E581: 20 C2 E4
00E584  1               
00E584  1               ; ----------------------------------------------------------------------------
00E584  1               ; Calculate and evaluate the difference between the loaded geometry record
00E584  1               ; and the base object at array offset zero.
00E584  1               ; ----------------------------------------------------------------------------
00E584  1               
00E584  1  20 D7 E4         jsr CalculateBaseGeometryDifference
00E587  1                                               ; $E584: 20 D7 E4
00E587  1               
00E587  1  20 02 E5         jsr EvaluateGeometryDifference
00E58A  1                                               ; $E587: 20 02 E5
00E58A  1               
00E58A  1  C9 02            cmp #$02                    ; $E58A: C9 02
00E58C  1  90 0A            bcc ApplyBaseObjectGeometry_CopyCurrent
00E58E  1                                               ; $E58C: 90 0A
00E58E  1               
00E58E  1               ; ----------------------------------------------------------------------------
00E58E  1               ; Geometry result is at least two.
00E58E  1               ;
00E58E  1               ; Build a vector using the parameter in $C5, then store the result in the base
00E58E  1               ; object's position/movement fields.
00E58E  1               ; ----------------------------------------------------------------------------
00E58E  1               
00E58E  1  A5 C5            lda $C5                     ; $E58E: A5 C5
00E590  1               
00E590  1  20 13 E5         jsr BuildGeometryVector     ; $E590: 20 13 E5
00E593  1  20 33 E5         jsr StoreBaseObjectPositionAndClearMovement
00E596  1                                               ; $E593: 20 33 E5
00E596  1               
00E596  1  38               sec                         ; $E596: 38
00E597  1  60               rts                         ; $E597: 60
00E598  1               
00E598  1               ; ----------------------------------------------------------------------------
00E598  1               ; Geometry result is below two.
00E598  1               ;
00E598  1               ; Initialize the base object from the current object and return carry clear.
00E598  1               ; ----------------------------------------------------------------------------
00E598  1               
00E598  1               ApplyBaseObjectGeometry_CopyCurrent: ; $E598
00E598  1  20 E6 E3         jsr InitializeBaseObjectFromCurrent
00E59B  1                                               ; $E598: 20 E6 E3
00E59B  1               
00E59B  1  18               clc                         ; $E59B: 18
00E59C  1  60               rts                         ; $E59C: 60
00E59D  1               
00E59D  1               ; ============================================================================
00E59D  1               ; $E59D-$E5CE
00E59D  1               ; Evaluate both current-object and base-object geometry, calculate a bounded
00E59D  1               ; shared vector parameter, apply that vector to the base object, and activate
00E59D  1               ; motion.
00E59D  1               ;
00E59D  1               ; This routine combines the geometry results from two separate record
00E59D  1               ; selections:
00E59D  1               ;
00E59D  1               ;   1. Selector-dependent record chosen by $E474.
00E59D  1               ;   2. Current-selector record chosen by $E46B.
00E59D  1               ; ============================================================================
00E59D  1               
00E59D  1               ; ----------------------------------------------------------------------------
00E59D  1               ; Contract:
00E59D  1               ;   Description: Initializes Shared Object Motion.
00E59D  1               ;   Entry: Registers: A
00E59D  1               ;   Returns/products: Registers/clobbers: A, X, Y
00E59D  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E59D  1               ;   Memory effects: $c5
00E59D  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E59D  1               ;          comparison, load, or store path and are not a stable API product.
00E59D  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00E59D  1               ; ----------------------------------------------------------------------------
00E59D  1               InitializeSharedObjectMotion:   ; $E59D
00E59D  1  20 74 E4         jsr SelectGeometryRecord_Default
00E5A0  1                                               ; $E59D: 20 74 E4
00E5A0  1               
00E5A0  1  20 C2 E4         jsr LoadGeometryRecord      ; $E5A0: 20 C2 E4
00E5A3  1               
00E5A3  1  20 DB E4         jsr CalculateCurrentGeometryDifference
00E5A6  1                                               ; $E5A3: 20 DB E4
00E5A6  1               
00E5A6  1  20 02 E5         jsr EvaluateGeometryDifference
00E5A9  1                                               ; $E5A6: 20 02 E5
00E5A9  1               
00E5A9  1  48               pha                         ; $E5A9: 48
00E5AA  1                                               ; Preserve the current-object geometry result.
00E5AA  1               
00E5AA  1               ; ----------------------------------------------------------------------------
00E5AA  1               ; Select and evaluate the corresponding geometry relative to the base object.
00E5AA  1               ; ----------------------------------------------------------------------------
00E5AA  1               
00E5AA  1  20 6B E4         jsr GetCurrentGeometryRecordOffset
00E5AD  1                                               ; $E5AA: 20 6B E4
00E5AD  1               
00E5AD  1  20 C2 E4         jsr LoadGeometryRecord      ; $E5AD: 20 C2 E4
00E5B0  1               
00E5B0  1  20 D7 E4         jsr CalculateBaseGeometryDifference
00E5B3  1                                               ; $E5B0: 20 D7 E4
00E5B3  1               
00E5B3  1  20 02 E5         jsr EvaluateGeometryDifference
00E5B6  1                                               ; $E5B3: 20 02 E5
00E5B6  1               
00E5B6  1  AA               tax                         ; $E5B6: AA
00E5B7  1                                               ; X = base-object geometry result.
00E5B7  1               
00E5B7  1  68               pla                         ; $E5B7: 68
00E5B8  1  A8               tay                         ; $E5B8: A8
00E5B9  1                                               ; Y = current-object geometry result.
00E5B9  1               
00E5B9  1               ; ----------------------------------------------------------------------------
00E5B9  1               ; Call the math helper at $E965 with:
00E5B9  1               ;
00E5B9  1               ;   A = $0F
00E5B9  1               ;   X = base-object result
00E5B9  1               ;   Y = current-object result
00E5B9  1               ;
00E5B9  1               ; Clamp its returned value to a maximum of $19.
00E5B9  1               ; ----------------------------------------------------------------------------
00E5B9  1               
00E5B9  1  A9 0F            lda #$0F                    ; $E5B9: A9 0F
00E5BB  1  20 65 E9         jsr CalculateScaledRatio                   ; $E5BB: 20 65 E9
00E5BE  1               
00E5BE  1  C9 19            cmp #$19                    ; $E5BE: C9 19
00E5C0  1  90 02            bcc InitializeSharedObjectMotion_Save
00E5C2  1                                               ; $E5C0: 90 02
00E5C2  1               
00E5C2  1  A9 19            lda #$19                    ; $E5C2: A9 19
00E5C4  1               
00E5C4  1               InitializeSharedObjectMotion_Save: ; $E5C4
00E5C4  1  85 C5            sta $C5                     ; $E5C4: 85 C5
00E5C6  1               
00E5C6  1               ; ----------------------------------------------------------------------------
00E5C6  1               ; Build and store the resulting vector in the base object.
00E5C6  1               ; ----------------------------------------------------------------------------
00E5C6  1               
00E5C6  1  20 13 E5         jsr BuildGeometryVector     ; $E5C6: 20 13 E5
00E5C9  1               
00E5C9  1  20 33 E5         jsr StoreBaseObjectPositionAndClearMovement
00E5CC  1                                               ; $E5C9: 20 33 E5
00E5CC  1               
00E5CC  1               ; ----------------------------------------------------------------------------
00E5CC  1               ; Mark base motion active.
00E5CC  1               ; ----------------------------------------------------------------------------
00E5CC  1               
00E5CC  1  E6 5C            inc BaseMotionActive            ; $E5CC: E6 5C
00E5CE  1               
00E5CE  1  60               rts                         ; $E5CE: 60
00E5CF  1               
00E5CF  1               ; ============================================================================
00E5CF  1               ; $E5CF-$E5F3
00E5CF  1               ; Build a short PPU/display queue entry in the buffer at $0300.
00E5CF  1               ;
00E5CF  1               ; The routine:
00E5CF  1               ;   1. Calls $EA3E with A=$22, X=$A8, Y=$03, and carry set.
00E5CF  1               ;   2. Saves the returned buffer index from X in $05.
00E5CF  1               ;   3. Writes three copies of tile/value $25 into $0300,X.
00E5CF  1               ;   4. Uses bit zero of ModeFlags to select one of two final buffer positions.
00E5CF  1               ;   5. Writes tile/value $AE at that selected position.
00E5CF  1               ;
00E5CF  1               ; The exact semantics of $EA3E are not yet decoded, but it appears to prepare
00E5CF  1               ; or reserve a display/PPU queue entry and return its starting index in X.
00E5CF  1               ; ============================================================================
00E5CF  1               
00E5CF  1               ; ----------------------------------------------------------------------------
00E5CF  1               ; Contract:
00E5CF  1               ;   Description: Queues Mode Indicator Tiles.
00E5CF  1               ;   Entry: Registers: A, X, Y; Memory: modeflags, $05
00E5CF  1               ;   Returns/products: Registers/clobbers: A, X, Y
00E5CF  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E5CF  1               ;   Memory effects: $05, $0300
00E5CF  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E5CF  1               ;          comparison, load, or store path and are not a stable API product.
00E5CF  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00E5CF  1               ; ----------------------------------------------------------------------------
00E5CF  1               QueueModeIndicatorTiles:        ; $E5CF
00E5CF  1  A9 22            lda #$22                    ; $E5CF: A9 22
00E5D1  1                                               ; Display/PPU destination parameter.
00E5D1  1               
00E5D1  1  A2 A8            ldx #$A8                    ; $E5D1: A2 A8
00E5D3  1                                               ; Tile, address, or queue parameter.
00E5D3  1               
00E5D3  1  A0 03            ldy #$03                    ; $E5D3: A0 03
00E5D5  1                                               ; Record length or field count.
00E5D5  1               
00E5D5  1  38               sec                         ; $E5D5: 38
00E5D6  1                                               ; Carry is an input to $EA3E.
00E5D6  1               
00E5D6  1  20 3E EA         jsr AllocateDisplayBufferRecord                   ; $E5D6: 20 3E EA
00E5D9  1                                               ; Prepare the queue entry.
00E5D9  1                                               ; Returns a buffer index in X.
00E5D9  1               
00E5D9  1               ; ----------------------------------------------------------------------------
00E5D9  1               ; Preserve the returned buffer index.
00E5D9  1               ; ----------------------------------------------------------------------------
00E5D9  1               
00E5D9  1  86 05            stx $05                     ; $E5D9: 86 05
00E5DB  1               
00E5DB  1               ; ----------------------------------------------------------------------------
00E5DB  1               ; Write three copies of $25 into consecutive bytes of the $0300 buffer.
00E5DB  1               ;
00E5DB  1               ; The loop writes:
00E5DB  1               ;
00E5DB  1               ;   $0300,X     = $25
00E5DB  1               ;   $0301,X     = $25
00E5DB  1               ;   $0302,X     = $25
00E5DB  1               ; ----------------------------------------------------------------------------
00E5DB  1               
00E5DB  1  A0 03            ldy #$03                    ; $E5DB: A0 03
00E5DD  1  A9 25            lda #$25                    ; $E5DD: A9 25
00E5DF  1               
00E5DF  1               QueueModeIndicatorTiles_Fill:   ; $E5DF
00E5DF  1  9D 00 03         sta $0300,x                 ; $E5DF: 9D 00 03
00E5E2  1  E8               inx                         ; $E5E2: E8
00E5E3  1               
00E5E3  1  88               dey                         ; $E5E3: 88
00E5E4  1  D0 F9            bne QueueModeIndicatorTiles_Fill
00E5E6  1                                               ; $E5E4: D0 F9
00E5E6  1               
00E5E6  1               ; ----------------------------------------------------------------------------
00E5E6  1               ; Select the final marker position according to bit zero of ModeFlags.
00E5E6  1               ;
00E5E6  1               ; Selected offset:
00E5E6  1               ;
00E5E6  1               ;   X = saved buffer index + ((ModeFlags & $01) * 2)
00E5E6  1               ; ----------------------------------------------------------------------------
00E5E6  1               
00E5E6  1  A5 40            lda ModeFlags               ; $E5E6: A5 40
00E5E8  1  29 01            and #$01                    ; $E5E8: 29 01
00E5EA  1  0A               asl                         ; $E5EA: 0A
00E5EB  1               
00E5EB  1  65 05            adc $05                     ; $E5EB: 65 05
00E5ED  1                                               ; Carry is clear after ASL because the input
00E5ED  1                                               ; can only be zero or one.
00E5ED  1               
00E5ED  1  AA               tax                         ; $E5ED: AA
00E5EE  1               
00E5EE  1               ; ----------------------------------------------------------------------------
00E5EE  1               ; Write marker tile/value $AE into the selected buffer position.
00E5EE  1               ; ----------------------------------------------------------------------------
00E5EE  1               
00E5EE  1  A9 AE            lda #$AE                    ; $E5EE: A9 AE
00E5F0  1  9D 00 03         sta $0300,x                 ; $E5F0: 9D 00 03
00E5F3  1               
00E5F3  1  60               rts                         ; $E5F3: 60
00E5F4  1               
00E5F4  1               ; ============================================================================
00E5F4  1               ; $E5F4
00E5F4  1               ; Standalone return entry.
00E5F4  1               ;
00E5F4  1               ; No decoded branch currently targets this byte, but it is a valid one-byte
00E5F4  1               ; routine/alternate return immediately before the random-number generator.
00E5F4  1               ; ============================================================================
00E5F4  1               
00E5F4  1               Return_E5F4:                    ; $E5F4
00E5F4  1  60               rts                         ; $E5F4: 60
00E5F5  1               
00E5F5  1               ; ============================================================================
00E5F5  1               ; $E5F5-$E610
00E5F5  1               ; Advance the 16-bit pseudo-random state by eight rounds.
00E5F5  1               ;
00E5F5  1               ; Random state:
00E5F5  1               ;   $19 = low/output byte
00E5F5  1               ;   $1A = high/feedback byte
00E5F5  1               ;
00E5F5  1               ; Working state:
00E5F5  1               ;   $DC = eight-round loop counter
00E5F5  1               ;
00E5F5  1               ; Return:
00E5F5  1               ;   A = updated $19
00E5F5  1               ;
00E5F5  1               ; The routine shifts the combined random state right. When the shifted-out bit
00E5F5  1               ; is clear, feedback masks $88 and $10 are XORed into $1A and $19.
00E5F5  1               ; ============================================================================
00E5F5  1               
00E5F5  1               ; ----------------------------------------------------------------------------
00E5F5  1               ; Contract:
00E5F5  1               ;   Description: Implements Advance Random State.
00E5F5  1               ;   Entry: Registers: A; Memory: randomstatelo, randomstatehi
00E5F5  1               ;   Returns/products: Registers/clobbers: A
00E5F5  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E5F5  1               ;   Memory effects: $dc, randomstatehi, randomstatelo
00E5F5  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E5F5  1               ;          comparison, load, or store path and are not a stable API product.
00E5F5  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 21.
00E5F5  1               ; ----------------------------------------------------------------------------
00E5F5  1               AdvanceRandomState:             ; $E5F5
00E5F5  1  A9 08            lda #$08                    ; $E5F5: A9 08
00E5F7  1  85 DC            sta $DC                     ; $E5F7: 85 DC
00E5F9  1               
00E5F9  1               ; ----------------------------------------------------------------------------
00E5F9  1               ; Load the low random-state byte once at the start of each round.
00E5F9  1               ; ----------------------------------------------------------------------------
00E5F9  1               
00E5F9  1               AdvanceRandomState_Loop:        ; $E5F9
00E5F9  1  A5 19            lda RandomStateLo           ; $E5F9: A5 19
00E5FB  1               
00E5FB  1               ; ----------------------------------------------------------------------------
00E5FB  1               ; Shift the combined 16-bit state right:
00E5FB  1               ;
00E5FB  1               ;   LSR $1A shifts the high byte and places its old bit zero in carry.
00E5FB  1               ;   ROR A shifts that carry into bit seven of the low byte.
00E5FB  1               ;
00E5FB  1               ; Carry after ROR contains the former bit zero of $19.
00E5FB  1               ; ----------------------------------------------------------------------------
00E5FB  1               
00E5FB  1  46 1A            lsr RandomStateHi           ; $E5FB: 46 1A
00E5FD  1  6A               ror                         ; $E5FD: 6A
00E5FE  1               
00E5FE  1               ; ----------------------------------------------------------------------------
00E5FE  1               ; If the shifted-out low bit was one, store the shifted low byte directly.
00E5FE  1               ; ----------------------------------------------------------------------------
00E5FE  1               
00E5FE  1  B0 0A            bcs AdvanceRandomState_SaveLow
00E600  1                                               ; $E5FE: B0 0A
00E600  1               
00E600  1               ; ----------------------------------------------------------------------------
00E600  1               ; The shifted-out low bit was zero.
00E600  1               ;
00E600  1               ; Apply feedback masks to both bytes:
00E600  1               ;
00E600  1               ;   $1A ^= $88
00E600  1               ;   A   ^= $10
00E600  1               ;
00E600  1               ; A is preserved on the stack while $1A is updated.
00E600  1               ; ----------------------------------------------------------------------------
00E600  1               
00E600  1  48               pha                         ; $E600: 48
00E601  1               
00E601  1  A5 1A            lda RandomStateHi           ; $E601: A5 1A
00E603  1  49 88            eor #$88                    ; $E603: 49 88
00E605  1  85 1A            sta RandomStateHi           ; $E605: 85 1A
00E607  1               
00E607  1  68               pla                         ; $E607: 68
00E608  1  49 10            eor #$10                    ; $E608: 49 10
00E60A  1               
00E60A  1               ; ----------------------------------------------------------------------------
00E60A  1               ; Save the updated low byte and continue for eight total rounds.
00E60A  1               ; ----------------------------------------------------------------------------
00E60A  1               
00E60A  1               AdvanceRandomState_SaveLow:     ; $E60A
00E60A  1  85 19            sta RandomStateLo           ; $E60A: 85 19
00E60C  1               
00E60C  1  C6 DC            dec $DC                     ; $E60C: C6 DC
00E60E  1  D0 E9            bne AdvanceRandomState_Loop ; $E60E: D0 E9
00E610  1               
00E610  1  60               rts                         ; $E610: 60
00E611  1               
00E611  1               ; ============================================================================
00E611  1               ; $E611-$E63D
00E611  1               ; Multiply an 8-bit value by a signed 16-bit value using eight rounds of
00E611  1               ; conditional addition and arithmetic right shifting.
00E611  1               ;
00E611  1               ; Entry:
00E611  1               ;   A = 8-bit multiplier
00E611  1               ;   Y = multiplicand low byte
00E611  1               ;   X = multiplicand high byte
00E611  1               ;
00E611  1               ; Working storage:
00E611  1               ;   $28     = shifting multiplier
00E611  1               ;   $2B/$2C = signed 16-bit multiplicand
00E611  1               ;   $29/$2A = signed 16-bit accumulator/result
00E611  1               ;
00E611  1               ; Exit:
00E611  1               ;   Y = result low byte
00E611  1               ;   X = result high byte
00E611  1               ;
00E611  1               ; The accumulator is arithmetically shifted right after every round. This
00E611  1               ; produces a fixed-point scaled result rather than the full 24-bit product.
00E611  1               ; ============================================================================
00E611  1               
00E611  1               MultiplyByteBySignedWord:       ; $E611
00E611  1  84 2B            sty $2B                     ; $E611: 84 2B
00E613  1                                               ; Save multiplicand low byte.
00E613  1               
00E613  1  86 2C            stx $2C                     ; $E613: 86 2C
00E615  1                                               ; Save multiplicand high byte.
00E615  1               
00E615  1  85 28            sta $28                     ; $E615: 85 28
00E617  1                                               ; Save the 8-bit multiplier.
00E617  1               
00E617  1               ; ----------------------------------------------------------------------------
00E617  1               ; Clear the signed 16-bit accumulator.
00E617  1               ; ----------------------------------------------------------------------------
00E617  1               
00E617  1  A9 00            lda #$00                    ; $E617: A9 00
00E619  1  85 29            sta $29                     ; $E619: 85 29
00E61B  1                                               ; Accumulator low byte.
00E61B  1               
00E61B  1  85 2A            sta $2A                     ; $E61B: 85 2A
00E61D  1                                               ; Accumulator high byte.
00E61D  1               
00E61D  1               ; ----------------------------------------------------------------------------
00E61D  1               ; Process all eight multiplier bits.
00E61D  1               ; ----------------------------------------------------------------------------
00E61D  1               
00E61D  1  A2 08            ldx #$08                    ; $E61D: A2 08
00E61F  1               
00E61F  1               MultiplyByteBySignedWord_Loop:  ; $E61F
00E61F  1  66 28            ror $28                     ; $E61F: 66 28
00E621  1                                               ; Shift the next multiplier bit into carry.
00E621  1               
00E621  1  90 0D            bcc MultiplyByteBySignedWord_Shift
00E623  1                                               ; $E621: 90 0D
00E623  1               
00E623  1               ; ----------------------------------------------------------------------------
00E623  1               ; The current multiplier bit is one.
00E623  1               ;
00E623  1               ; Add the signed 16-bit multiplicand to the accumulator.
00E623  1               ; ----------------------------------------------------------------------------
00E623  1               
00E623  1  18               clc                         ; $E623: 18
00E624  1               
00E624  1  A5 29            lda $29                     ; $E624: A5 29
00E626  1  65 2B            adc $2B                     ; $E626: 65 2B
00E628  1  85 29            sta $29                     ; $E628: 85 29
00E62A  1               
00E62A  1  A5 2A            lda $2A                     ; $E62A: A5 2A
00E62C  1  65 2C            adc $2C                     ; $E62C: 65 2C
00E62E  1  85 2A            sta $2A                     ; $E62E: 85 2A
00E630  1               
00E630  1               ; ----------------------------------------------------------------------------
00E630  1               ; Arithmetically shift the signed accumulator right by one bit.
00E630  1               ;
00E630  1               ; CMP #$80 copies the sign bit of the high accumulator byte into carry:
00E630  1               ;
00E630  1               ;   $2A >= $80 -> carry set
00E630  1               ;   $2A <  $80 -> carry clear
00E630  1               ;
00E630  1               ; ROR $2A therefore preserves the sign bit. ROR $29 completes the signed
00E630  1               ; 16-bit right shift.
00E630  1               ; ----------------------------------------------------------------------------
00E630  1               
00E630  1               MultiplyByteBySignedWord_Shift: ; $E630
00E630  1  C9 80            cmp #$80                    ; $E630: C9 80
00E632  1               
00E632  1  66 2A            ror $2A                     ; $E632: 66 2A
00E634  1  66 29            ror $29                     ; $E634: 66 29
00E636  1               
00E636  1               ; ----------------------------------------------------------------------------
00E636  1               ; Continue until all eight multiplier bits have been processed.
00E636  1               ; ----------------------------------------------------------------------------
00E636  1               
00E636  1  CA               dex                         ; $E636: CA
00E637  1  D0 E6            bne MultiplyByteBySignedWord_Loop
00E639  1                                               ; $E637: D0 E6
00E639  1               
00E639  1               ; ----------------------------------------------------------------------------
00E639  1               ; Return the signed 16-bit result in Y:X.
00E639  1               ; ----------------------------------------------------------------------------
00E639  1               
00E639  1  A4 29            ldy $29                     ; $E639: A4 29
00E63B  1  A6 2A            ldx $2A                     ; $E63B: A6 2A
00E63D  1               
00E63D  1  60               rts                         ; $E63D: 60
00E63E  1               
00E63E  1               ; ============================================================================
00E63E  1               ; $E63E-$E672
00E63E  1               ; Perform an eight-round restoring division or normalization operation.
00E63E  1               ;
00E63E  1               ; Entry:
00E63E  1               ;   Y       = initial low working byte
00E63E  1               ;   A       = initial high working byte
00E63E  1               ;   $2D/$2E = 16-bit divisor or comparison value
00E63E  1               ;   $28     = quotient/result shift register
00E63E  1               ;
00E63E  1               ; Working values:
00E63E  1               ;   $29/$2A = 16-bit partial remainder
00E63E  1               ;
00E63E  1               ; Exit:
00E63E  1               ;   A = quotient/result byte from $28
00E63E  1               ;   X = adjustment or status value
00E63E  1               ;
00E63E  1               ; Failure/overflow:
00E63E  1               ;   A = $00
00E63E  1               ;
00E63E  1               ; The exact numeric interpretation should remain provisional until all callers
00E63E  1               ; are analyzed, but the implementation follows a restoring-division pattern.
00E63E  1               ; ============================================================================
00E63E  1               
00E63E  1               ; ----------------------------------------------------------------------------
00E63E  1               ; Contract:
00E63E  1               ;   Description: Implements Divide Or Normalize Word.
00E63E  1               ;   Entry: Registers: A, X, Y; Memory: $29, $2d, $2a, $2e
00E63E  1               ;   Returns/products: Registers/clobbers: A, X, Y
00E63E  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E63E  1               ;   Memory effects: $29, $2a
00E63E  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E63E  1               ;          comparison, load, or store path and are not a stable API product.
00E63E  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 2.
00E63E  1               ; ----------------------------------------------------------------------------
00E63E  1               DivideOrNormalizeWord:          ; $E63E
00E63E  1  84 29            sty $29                     ; $E63E: 84 29
00E640  1  85 2A            sta $2A                     ; $E640: 85 2A
00E642  1               
00E642  1  A2 08            ldx #$08                    ; $E642: A2 08
00E644  1                                               ; Process eight output bits.
00E644  1               
00E644  1               ; ----------------------------------------------------------------------------
00E644  1               ; Add the divisor to the current partial remainder.
00E644  1               ; ----------------------------------------------------------------------------
00E644  1               
00E644  1               DivideOrNormalizeWord_Loop:     ; $E644
00E644  1  18               clc                         ; $E644: 18
00E645  1               
00E645  1  A5 29            lda $29                     ; $E645: A5 29
00E647  1  65 2D            adc $2D                     ; $E647: 65 2D
00E649  1  A8               tay                         ; $E649: A8
00E64A  1               
00E64A  1  A5 2A            lda $2A                     ; $E64A: A5 2A
00E64C  1  65 2E            adc $2E                     ; $E64C: 65 2E
00E64E  1               
00E64E  1               ; ----------------------------------------------------------------------------
00E64E  1               ; If the addition overflowed, retain the previous partial remainder.
00E64E  1               ;
00E64E  1               ; Otherwise, save the candidate remainder from A:Y.
00E64E  1               ; ----------------------------------------------------------------------------
00E64E  1               DivideOrNormalizeWord_CheckCarry: ; $E64E
00E64E  1  90 04            bcc DivideOrNormalizeWord_Shift
00E650  1                                               ; $E64E: 90 04
00E650  1               
00E650  1  84 29            sty $29                     ; $E650: 84 29
00E652  1  85 2A            sta $2A                     ; $E652: 85 2A
00E654  1               
00E654  1               ; ----------------------------------------------------------------------------
00E654  1               ; Shift the quotient/result and partial remainder left.
00E654  1               ; ----------------------------------------------------------------------------
00E654  1               
00E654  1               DivideOrNormalizeWord_Shift:    ; $E654
00E654  1  26 28            rol $28                     ; $E654: 26 28
00E656  1               
00E656  1  06 29            asl $29                     ; $E656: 06 29
00E658  1  26 2A            rol $2A                     ; $E658: 26 2A
00E65A  1               
00E65A  1  B0 14            bcs DivideOrNormalizeWord_Overflow
00E65C  1                                               ; $E65A: B0 14
00E65C  1               
00E65C  1               ; ----------------------------------------------------------------------------
00E65C  1               ; Subtract the divisor to prepare the next candidate remainder.
00E65C  1               ; ----------------------------------------------------------------------------
00E65C  1               
00E65C  1  38               sec                         ; $E65C: 38
00E65D  1               
00E65D  1  A5 29            lda $29                     ; $E65D: A5 29
00E65F  1  E5 2D            sbc $2D                     ; $E65F: E5 2D
00E661  1  A8               tay                         ; $E661: A8
00E662  1               
00E662  1  A5 2A            lda $2A                     ; $E662: A5 2A
00E664  1  E5 2E            sbc $2E                     ; $E664: E5 2E
00E666  1               
00E666  1  CA               dex                         ; $E666: CA
00E667  1  D0 E5            bne DivideOrNormalizeWord_CheckCarry
00E669  1                                               ; $E667: D0 E5
00E669  1                                               ; Continue from the quotient/remainder shift.
00E669  1               
00E669  1               ; ----------------------------------------------------------------------------
00E669  1               ; Return the quotient/result byte.
00E669  1               ;
00E669  1               ; X is adjusted according to carry from the final subtraction.
00E669  1               ; ----------------------------------------------------------------------------
00E669  1               
00E669  1  A5 28            lda $28                     ; $E669: A5 28
00E66B  1               
00E66B  1  CA               dex                         ; $E66B: CA
00E66C  1  B0 01            bcs DivideOrNormalizeWord_Return
00E66E  1                                               ; $E66C: B0 01
00E66E  1               
00E66E  1  CA               dex                         ; $E66E: CA
00E66F  1               
00E66F  1               DivideOrNormalizeWord_Return:   ; $E66F
00E66F  1  60               rts                         ; $E66F: 60
00E670  1               
00E670  1               ; ----------------------------------------------------------------------------
00E670  1               ; Overflow path.
00E670  1               ; ----------------------------------------------------------------------------
00E670  1               
00E670  1               DivideOrNormalizeWord_Overflow: ; $E670
00E670  1  A9 00            lda #$00                    ; $E670: A9 00
00E672  1  60               rts                         ; $E672: 60
00E673  1               
00E673  1               ; ============================================================================
00E673  1               ; $E673-$E6C0
00E673  1               ; Build transformed movement/vector components from object state.
00E673  1               ;
00E673  1               ; Three entry paths are present:
00E673  1               ;
00E673  1               ;   $E673 uses movement values at $056D/$056E.
00E673  1               ;   $E695 uses movement values at $056B/$056C.
00E673  1               ;   $E6B7 clears all four transformed results.
00E673  1               ;
00E673  1               ; Results:
00E673  1               ;   $31/$32 = first transformed 16-bit component
00E673  1               ;   $2F/$30 = second transformed 16-bit component
00E673  1               ;
00E673  1               ; The transformation helper is MultiplyByteBySignedWord at $E611.
00E673  1               ; ============================================================================
00E673  1               
00E673  1               ; ----------------------------------------------------------------------------
00E673  1               ; Contract:
00E673  1               ;   Description: Implements Build Current Movement Transforms.
00E673  1               ;   Entry: Registers: A, X, Y; Memory: $056d, $056e, $cf, $d1, $056b, $056c
00E673  1               ;   Returns/products: Registers/clobbers: A, X, Y
00E673  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E673  1               ;   Memory effects: $31, selectionvalue0, $2f, $30, $32
00E673  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E673  1               ;          comparison, load, or store path and are not a stable API product.
00E673  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00E673  1               ; ----------------------------------------------------------------------------
00E673  1               BuildCurrentMovementTransforms: ; $E673
00E673  1  AC 6D 05         ldy $056D                   ; $E673: AC 6D 05
00E676  1  AE 6E 05         ldx $056E                   ; $E676: AE 6E 05
00E679  1               
00E679  1  A5 CF            lda $CF                     ; $E679: A5 CF
00E67B  1  20 11 E6         jsr MultiplyByteBySignedWord
00E67E  1                                               ; $E67B: 20 11 E6
00E67E  1               
00E67E  1  84 31            sty $31                     ; $E67E: 84 31
00E680  1  86 32            stx SelectionValue0         ; $E680: 86 32
00E682  1               
00E682  1  AC 6D 05         ldy $056D                   ; $E682: AC 6D 05
00E685  1  AE 6E 05         ldx $056E                   ; $E685: AE 6E 05
00E688  1               
00E688  1  A5 D1            lda $D1                     ; $E688: A5 D1
00E68A  1  20 11 E6         jsr MultiplyByteBySignedWord
00E68D  1                                               ; $E68A: 20 11 E6
00E68D  1               
00E68D  1  84 2F            sty $2F                     ; $E68D: 84 2F
00E68F  1  86 30            stx $30                     ; $E68F: 86 30
00E691  1               
00E691  1               ; ----------------------------------------------------------------------------
00E691  1               ; X is cleared and BEQ is therefore unconditional.
00E691  1               ; ----------------------------------------------------------------------------
00E691  1               
00E691  1  A2 00            ldx #$00                    ; $E691: A2 00
00E693  1  F0 2C            beq ProjectObjectCoordinates
00E695  1                                               ; $E693: F0 2C
00E695  1               
00E695  1               ; ----------------------------------------------------------------------------
00E695  1               ; Alternate entry using the base movement values at $056B/$056C.
00E695  1               ; ----------------------------------------------------------------------------
00E695  1               
00E695  1               ; ----------------------------------------------------------------------------
00E695  1               ; Contract:
00E695  1               ;   Description: Implements Build Base Movement Transforms.
00E695  1               ;   Entry: Registers: A, X, Y; Memory: $056b, $056c, $cf, $d1, $053a, $d2
00E695  1               ;   Returns/products: Registers/clobbers: A, X, Y
00E695  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E695  1               ;   Memory effects: $31, $32, $2f, $30
00E695  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E695  1               ;          comparison, load, or store path and are not a stable API product.
00E695  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00E695  1               ; ----------------------------------------------------------------------------
00E695  1               BuildBaseMovementTransforms:    ; $E695
00E695  1  AC 6B 05         ldy $056B                   ; $E695: AC 6B 05
00E698  1  AE 6C 05         ldx $056C                   ; $E698: AE 6C 05
00E69B  1               
00E69B  1  A5 CF            lda $CF                     ; $E69B: A5 CF
00E69D  1  20 11 E6         jsr MultiplyByteBySignedWord
00E6A0  1                                               ; $E69D: 20 11 E6
00E6A0  1               
00E6A0  1  84 31            sty $31                     ; $E6A0: 84 31
00E6A2  1  86 32            stx SelectionValue0                     ; $E6A2: 86 32
00E6A4  1               
00E6A4  1  AC 6B 05         ldy $056B                   ; $E6A4: AC 6B 05
00E6A7  1  AE 6C 05         ldx $056C                   ; $E6A7: AE 6C 05
00E6AA  1               
00E6AA  1  A5 D1            lda $D1                     ; $E6AA: A5 D1
00E6AC  1  20 11 E6         jsr MultiplyByteBySignedWord
00E6AF  1                                               ; $E6AC: 20 11 E6
00E6AF  1               
00E6AF  1  84 2F            sty $2F                     ; $E6AF: 84 2F
00E6B1  1  86 30            stx $30                     ; $E6B1: 86 30
00E6B3  1               
00E6B3  1  A2 00            ldx #$00                    ; $E6B3: A2 00
00E6B5  1  F0 0A            beq ProjectObjectCoordinates
00E6B7  1                                               ; $E6B5: F0 0A
00E6B7  1               
00E6B7  1               ; ----------------------------------------------------------------------------
00E6B7  1               ; Alternate entry that clears every transformed component.
00E6B7  1               ; ----------------------------------------------------------------------------
00E6B7  1               
00E6B7  1               ; ----------------------------------------------------------------------------
00E6B7  1               ; Contract:
00E6B7  1               ;   Description: Clears or resets Movement Transforms.
00E6B7  1               ;   Entry: Registers: A, X, Y; Memory: $053a, $d2, $053b, $d3, $ce, $cc, $cd, $31
00E6B7  1               ;   Returns/products: Registers/clobbers: A, X, Y
00E6B7  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E6B7  1               ;   Memory effects: $31, $32, $2f, $30, $06, $08, $09, $2d
00E6B7  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E6B7  1               ;          comparison, load, or store path and are not a stable API product.
00E6B7  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 15.
00E6B7  1               ; ----------------------------------------------------------------------------
00E6B7  1               ClearMovementTransforms:        ; $E6B7
00E6B7  1  A9 00            lda #$00                    ; $E6B7: A9 00
00E6B9  1               
00E6B9  1  85 31            sta $31                     ; $E6B9: 85 31
00E6BB  1  85 32            sta SelectionValue0                     ; $E6BB: 85 32
00E6BD  1  85 2F            sta $2F                     ; $E6BD: 85 2F
00E6BF  1  85 30            sta $30                     ; $E6BF: 85 30
00E6C1  1               
00E6C1  1               ; ============================================================================
00E6C1  1               ; $E6C1-$E737
00E6C1  1               ; Project one object's coordinates through the current transformation state.
00E6C1  1               ;
00E6C1  1               ; Entry:
00E6C1  1               ;   X = source object offset
00E6C1  1               ;
00E6C1  1               ; Working values:
00E6C1  1               ;   $06     = saved object offset
00E6C1  1               ;   $08/$09 = adjusted source vertical coordinate
00E6C1  1               ;   $2D/$2E = transformed intermediate vector
00E6C1  1               ;   $36/$37 = projected horizontal result
00E6C1  1               ;   $38/$39 = projected vertical result
00E6C1  1               ;
00E6C1  1               ; Return:
00E6C1  1               ;   C = clear when projection succeeds
00E6C1  1               ;   C = set when projection fails or lies outside the accepted range
00E6C1  1               ;
00E6C1  1               ; On success, selected projections are written to:
00E6C1  1               ;   $03BC,X
00E6C1  1               ;   $03DE,X
00E6C1  1               ; ============================================================================
00E6C1  1               
00E6C1  1               ProjectObjectCoordinates:       ; $E6C1
00E6C1  1  86 06            stx $06                     ; $E6C1: 86 06
00E6C3  1               
00E6C3  1               ; ----------------------------------------------------------------------------
00E6C3  1               ; Add the global vertical offset $D2/$D3 to the object's vertical coordinate.
00E6C3  1               ; ----------------------------------------------------------------------------
00E6C3  1               
00E6C3  1  18               clc                         ; $E6C3: 18
00E6C4  1               
00E6C4  1  BD 3A 05         lda $053A,x                 ; $E6C4: BD 3A 05
00E6C7  1  65 D2            adc $D2                     ; $E6C7: 65 D2
00E6C9  1  85 08            sta $08                     ; $E6C9: 85 08
00E6CB  1  A8               tay                         ; $E6CB: A8
00E6CC  1               
00E6CC  1  BD 3B 05         lda $053B,x                 ; $E6CC: BD 3B 05
00E6CF  1  65 D3            adc $D3                     ; $E6CF: 65 D3
00E6D1  1  85 09            sta $09                     ; $E6D1: 85 09
00E6D3  1  AA               tax                         ; $E6D3: AA
00E6D4  1               
00E6D4  1               ; ----------------------------------------------------------------------------
00E6D4  1               ; Scale or transform the adjusted coordinate using parameter $CE.
00E6D4  1               ; ----------------------------------------------------------------------------
00E6D4  1               
00E6D4  1  A5 CE            lda $CE                     ; $E6D4: A5 CE
00E6D6  1  20 11 E6         jsr MultiplyByteBySignedWord
00E6D9  1                                               ; $E6D6: 20 11 E6
00E6D9  1               
00E6D9  1               ; ----------------------------------------------------------------------------
00E6D9  1               ; Add global offsets $CC/$CD to the transformed result.
00E6D9  1               ; ----------------------------------------------------------------------------
00E6D9  1               
00E6D9  1  18               clc                         ; $E6D9: 18
00E6DA  1               
00E6DA  1  98               tya                         ; $E6DA: 98
00E6DB  1  65 CC            adc $CC                     ; $E6DB: 65 CC
00E6DD  1  A8               tay                         ; $E6DD: A8
00E6DE  1               
00E6DE  1  8A               txa                         ; $E6DE: 8A
00E6DF  1  65 CD            adc $CD                     ; $E6DF: 65 CD
00E6E1  1  AA               tax                         ; $E6E1: AA
00E6E2  1               
00E6E2  1               ; ----------------------------------------------------------------------------
00E6E2  1               ; Subtract transformed component $31/$32 and divide the result by two.
00E6E2  1               ; ----------------------------------------------------------------------------
00E6E2  1               
00E6E2  1  98               tya                         ; $E6E2: 98
00E6E3  1  38               sec                         ; $E6E3: 38
00E6E4  1  E5 31            sbc $31                     ; $E6E4: E5 31
00E6E6  1  85 2D            sta $2D                     ; $E6E6: 85 2D
00E6E8  1               
00E6E8  1  8A               txa                         ; $E6E8: 8A
00E6E9  1  E5 32            sbc SelectionValue0         ; $E6E9: E5 32
00E6EB  1               
00E6EB  1  4A               lsr                         ; $E6EB: 4A
00E6EC  1  85 2E            sta $2E                     ; $E6EC: 85 2E
00E6EE  1  66 2D            ror $2D                     ; $E6EE: 66 2D
00E6F0  1               
00E6F0  1               ; ----------------------------------------------------------------------------
00E6F0  1               ; Transform the adjusted source coordinate using parameter $D0.
00E6F0  1               ; ----------------------------------------------------------------------------
00E6F0  1               
00E6F0  1  A4 08            ldy $08                     ; $E6F0: A4 08
00E6F2  1  A6 09            ldx $09                     ; $E6F2: A6 09
00E6F4  1               
00E6F4  1  A5 D0            lda $D0                     ; $E6F4: A5 D0
00E6F6  1  20 11 E6         jsr MultiplyByteBySignedWord
00E6F9  1                                               ; $E6F6: 20 11 E6
00E6F9  1               
00E6F9  1               ; ----------------------------------------------------------------------------
00E6F9  1               ; Add transformed component $2F/$30.
00E6F9  1               ; ----------------------------------------------------------------------------
00E6F9  1               
00E6F9  1  18               clc                         ; $E6F9: 18
00E6FA  1               
00E6FA  1  98               tya                         ; $E6FA: 98
00E6FB  1  65 2F            adc $2F                     ; $E6FB: 65 2F
00E6FD  1  A8               tay                         ; $E6FD: A8
00E6FE  1               
00E6FE  1  8A               txa                         ; $E6FE: 8A
00E6FF  1  65 30            adc $30                     ; $E6FF: 65 30
00E701  1               
00E701  1               ; ----------------------------------------------------------------------------
00E701  1               ; Normalize or divide the result through the arithmetic helper at $E63E.
00E701  1               ; ----------------------------------------------------------------------------
00E701  1               
00E701  1  20 3E E6         jsr DivideOrNormalizeWord   ; $E701: 20
00E704  1                   ; ----------------------------------------------------------------------------
00E704  1               ; Reject a zero normalization result.
00E704  1               ; ----------------------------------------------------------------------------
00E704  1               
00E704  1  F0 30            beq ProjectObjectCoordinates_Fail
00E706  1                                               ; $E704: F0 30
00E706  1               
00E706  1               ; ----------------------------------------------------------------------------
00E706  1               ; Convert the returned vertical result into the projected display coordinate.
00E706  1               ; ----------------------------------------------------------------------------
00E706  1               
00E706  1  E9 00            sbc #$00                    ; $E706: E9 00
00E708  1  49 7F            eor #$7F                    ; $E708: 49 7F
00E70A  1               
00E70A  1  85 38            sta ObjectScreenY           ; $E70A: 85 38
00E70C  1  86 39            stx ObjectScreenYHi         ; $E70C: 86 39
00E70E  1               
00E70E  1               ; ----------------------------------------------------------------------------
00E70E  1               ; Restore the source object offset and normalize its horizontal coordinate.
00E70E  1               ; ----------------------------------------------------------------------------
00E70E  1               
00E70E  1  A6 06            ldx $06                     ; $E70E: A6 06
00E710  1               
00E710  1  BC 09 05         ldy $0509,x                 ; $E710: BC 09 05
00E713  1  BD 0A 05         lda $050A,x                 ; $E713: BD 0A 05
00E716  1               
00E716  1  20 3E E6         jsr DivideOrNormalizeWord   ; $E716: 20 3E E6
00E719  1               
00E719  1  F0 1B            beq ProjectObjectCoordinates_Fail
00E71B  1                                               ; $E719: F0 1B
00E71B  1               
00E71B  1               ; ----------------------------------------------------------------------------
00E71B  1               ; Convert the returned horizontal result into the projected display coordinate.
00E71B  1               ; ----------------------------------------------------------------------------
00E71B  1               
00E71B  1  69 80            adc #$80                    ; $E71B: 69 80
00E71D  1               
00E71D  1  85 36            sta ObjectScreenX           ; $E71D: 85 36
00E71F  1  86 37            stx ObjectScreenXHi         ; $E71F: 86 37
00E721  1               
00E721  1               ; ----------------------------------------------------------------------------
00E721  1               ; Convert the source object offset to its display-array index.
00E721  1               ; ----------------------------------------------------------------------------
00E721  1               
00E721  1  A6 06            ldx $06                     ; $E721: A6 06
00E723  1               
00E723  1  20 38 E7         jsr ConvertObjectOffsetToDisplayIndex
00E726  1                                               ; $E723: 20 38 E7
00E726  1               
00E726  1               ; ----------------------------------------------------------------------------
00E726  1               ; Display indices $22 and above return without writing to the projection
00E726  1               ; arrays. Carry remains set from CPX #$22 in that case.
00E726  1               ; ----------------------------------------------------------------------------
00E726  1               
00E726  1  E0 22            cpx #$22                    ; $E726: E0 22
00E728  1  B0 0B            bcs ProjectObjectCoordinates_Return
00E72A  1                                               ; $E728: B0 0B
00E72A  1               
00E72A  1               ; ----------------------------------------------------------------------------
00E72A  1               ; Save the projected horizontal and vertical coordinates.
00E72A  1               ; ----------------------------------------------------------------------------
00E72A  1               
00E72A  1  A5 36            lda ObjectScreenX           ; $E72A: A5 36
00E72C  1  9D BC 03         sta $03BC,x                 ; $E72C: 9D BC 03
00E72F  1               
00E72F  1  A5 38            lda ObjectScreenY           ; $E72F: A5 38
00E731  1  9D DE 03         sta $03DE,x                 ; $E731: 9D DE 03
00E734  1               
00E734  1  18               clc                         ; $E734: 18
00E735  1               
00E735  1               ProjectObjectCoordinates_Return: ; $E735
00E735  1  60               rts                         ; $E735: 60
00E736  1               
00E736  1               ; ----------------------------------------------------------------------------
00E736  1               ; A normalization failure returns carry set.
00E736  1               ; ----------------------------------------------------------------------------
00E736  1               
00E736  1               ProjectObjectCoordinates_Fail:  ; $E736
00E736  1  38               sec                         ; $E736: 38
00E737  1  60               rts                         ; $E737: 60
00E738  1               
00E738  1               ; ============================================================================
00E738  1               ; $E738-$E740
00E738  1               ; Convert an object-array offset into a display-array index.
00E738  1               ;
00E738  1               ; Entry:
00E738  1               ;   X = even object-array offset
00E738  1               ;
00E738  1               ; Calculation:
00E738  1               ;   X = (X / 2) + $C9 + 1
00E738  1               ;
00E738  1               ; Exit:
00E738  1               ;   X = converted display-array index
00E738  1               ;   Flags reflect CPX #$16
00E738  1               ;
00E738  1               ; This helper does not branch on the final comparison. Callers inspect X or
00E738  1               ; the returned flags themselves.
00E738  1               ; ============================================================================
00E738  1               
00E738  1               ; ----------------------------------------------------------------------------
00E738  1               ; Contract:
00E738  1               ;   Description: Implements Convert Object Offset To Display Index.
00E738  1               ;   Entry: Registers: A, X; Memory: spritesortbaseindex
00E738  1               ;   Returns/products: Registers/clobbers: A, X; Flags: condition flags may carry result state
00E738  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E738  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00E738  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E738  1               ;          comparison, load, or store path and are not a stable API product.
00E738  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 5.
00E738  1               ; ----------------------------------------------------------------------------
00E738  1               ConvertObjectOffsetToDisplayIndex: ; $E738
00E738  1  8A               txa                         ; $E738: 8A
00E739  1  4A               lsr                         ; $E739: 4A
00E73A  1                                               ; Divide the even object offset by two.
00E73A  1               
00E73A  1  65 C9            adc SpriteSortBaseIndex        ; $E73A: 65 C9
00E73C  1                                               ; Carry from LSR is normally clear for even
00E73C  1                                               ; object offsets.
00E73C  1               
00E73C  1  AA               tax                         ; $E73C: AA
00E73D  1  E8               inx                         ; $E73D: E8
00E73E  1               
00E73E  1  E0 16            cpx #$16                    ; $E73E: E0 16
00E740  1  60               rts                         ; $E740: 60
00E741  1               
00E741  1               ; ============================================================================
00E741  1               ; $E741-$E760
00E741  1               ; Initialize rendering state and copy 13 bytes from RenderingStateTable.
00E741  1               ;
00E741  1               ; Two effective entry points exist:
00E741  1               ;
00E741  1               ;   $E741:
00E741  1               ;       Sets ObjectScreenY to $F0 and forces carry clear before selecting the table
00E741  1               ;       range beginning at index $0C.
00E741  1               ;
00E741  1               ;   $E746:
00E741  1               ;       Uses incoming carry to choose between two table ranges:
00E741  1               ;
00E741  1               ;         C=0 -> start at table index $0C
00E741  1               ;         C=1 -> start at table index $19 and set bit 1 of $DD
00E741  1               ;
00E741  1               ; The selected 13 bytes are copied in reverse order into zero-page $C7-$D3.
00E741  1               ; ============================================================================
00E741  1               
00E741  1               InitializeRenderingState:       ; $E741
00E741  1  A9 F0            lda #$F0                    ; $E741: A9 F0
00E743  1  85 38            sta ObjectScreenY           ; $E743: 85 38
00E745  1                                               ; Default projected/display coordinate.
00E745  1               
00E745  1  18               clc                         ; $E745: 18
00E746  1               
00E746  1               ; ----------------------------------------------------------------------------
00E746  1               ; Alternate entry that preserves caller-supplied carry.
00E746  1               ; ----------------------------------------------------------------------------
00E746  1               
00E746  1               ; ----------------------------------------------------------------------------
00E746  1               ; Contract:
00E746  1               ;   Description: Initializes Rendering State From Carry.
00E746  1               ;   Entry: Registers: A, X, Y; Memory: ppuctrlshadow, renderingstatetable
00E746  1               ;   Returns/products: Registers/clobbers: A, X, Y
00E746  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E746  1               ;   Memory effects: ppuctrlshadow, $c7
00E746  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E746  1               ;          comparison, load, or store path and are not a stable API product.
00E746  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00E746  1               ; ----------------------------------------------------------------------------
00E746  1               InitializeRenderingStateFromCarry: ; $E746
00E746  1  A5 DD            lda PpuCtrlShadow           ; $E746: A5 DD
00E748  1  29 FD            and #$FD                    ; $E748: 29 FD
00E74A  1                                               ; Clear bit 1 by default.
00E74A  1               
00E74A  1  A0 0C            ldy #$0C                    ; $E74A: A0 0C
00E74C  1                                               ; Default table range ends at index $0C.
00E74C  1               
00E74C  1  90 04            bcc InitializeRenderingState_SaveFlags
00E74E  1                                               ; $E74C: 90 04
00E74E  1               
00E74E  1               ; ----------------------------------------------------------------------------
00E74E  1               ; Carry-set path.
00E74E  1               ;
00E74E  1               ; Select the second 13-byte range and set bit 1 of $DD.
00E74E  1               ; ----------------------------------------------------------------------------
00E74E  1               
00E74E  1  A0 19            ldy #$19                    ; $E74E: A0 19
00E750  1  09 02            ora #$02                    ; $E750: 09 02
00E752  1               
00E752  1               InitializeRenderingState_SaveFlags: ; $E752
00E752  1  85 DD            sta PpuCtrlShadow           ; $E752: 85 DD
00E754  1               
00E754  1               ; ----------------------------------------------------------------------------
00E754  1               ; Copy 13 bytes in reverse order.
00E754  1               ;
00E754  1               ; Source indices:
00E754  1               ;
00E754  1               ;   C clear: $0C down to $00
00E754  1               ;   C set:   $19 down to $0D
00E754  1               ;
00E754  1               ; Destination:
00E754  1               ;
00E754  1               ;   $D3 down to $C7
00E754  1               ; ----------------------------------------------------------------------------
00E754  1               
00E754  1  A2 0C            ldx #$0C                    ; $E754: A2 0C
00E756  1               
00E756  1               InitializeRenderingState_CopyLoop: ; $E756
00E756  1  B9 61 E7         lda RenderingStateTable,y   ; $E756: B9 61 E7
00E759  1  95 C7            sta ObjectListFlag,x                   ; $E759: 95 C7
00E75B  1               
00E75B  1  88               dey                         ; $E75B: 88
00E75C  1  CA               dex                         ; $E75C: CA
00E75D  1  10 F7            bpl InitializeRenderingState_CopyLoop
00E75F  1                                               ; $E75D: 10 F7
00E75F  1               
00E75F  1               ; ----------------------------------------------------------------------------
00E75F  1               ; Return carry set.
00E75F  1               ; ----------------------------------------------------------------------------
00E75F  1               
00E75F  1  38               sec                         ; $E75F: 38
00E760  1  60               rts                         ; $E760: 60
00E761  1               
00E761  1               ; ============================================================================
00E761  1               ; $E761-$E77A
00E761  1               ; Rendering-state lookup data.
00E761  1               ;
00E761  1               ; The initialization routine copies one of two 13-byte ranges:
00E761  1               ;
00E761  1               ;   Range 0:
00E761  1               ;       indices $00-$0C
00E761  1               ;
00E761  1               ;   Range 1:
00E761  1               ;       indices $0D-$19
00E761  1               ;
00E761  1               ; Both ranges are copied backward into zero-page $C7-$D3.
00E761  1               ; ============================================================================
00E761  1               
00E761  1               RenderingStateTable:            ; $E761
00E761  1               
00E761  1               ; First 13-byte state.
00E761  1               RenderingStateTable_Default:    ; $E761, indices $00-$0C
00E761  1  00 15 00 14      .byte $00,$15,$00,$14,$00,$14,$2D
00E765  1  00 14 2D     
00E768  1  58 3D 92 D2      .byte $58,$3D,$92,$D2,$FB,$F4
00E76C  1  FB F4        
00E76E  1               
00E76E  1               ; Second 13-byte state.
00E76E  1               RenderingStateTable_Alternate:  ; $E76E, indices $0D-$19
00E76E  1  08 0D 15 21      .byte $08,$0D,$15,$21,$06,$42,$16
00E772  1  06 42 16     
00E775  1  98 F7 DA 86      .byte $98,$F7,$DA,$86,$6F,$02
00E779  1  6F 02        
00E77B  1               
00E77B  1               ; ============================================================================
00E77B  1               ; $E77B-$E7BB
00E77B  1               ; Expand a sprite-record list into the OAM shadow buffer at $0200.
00E77B  1               ;
00E77B  1               ; Entry:
00E77B  1               ;   A = index into the pointer table at $0400
00E77B  1               ;
00E77B  1               ; Pointer table:
00E77B  1               ;   $0400/$0401 contains little-endian source pointers.
00E77B  1               ;   A is doubled before indexing the pointer table.
00E77B  1               ;
00E77B  1               ; Source record format:
00E77B  1               ;
00E77B  1               ;   byte 0:
00E77B  1               ;       number of four-byte sprite records
00E77B  1               ;
00E77B  1               ;   each sprite record:
00E77B  1               ;       byte 0 = relative Y coordinate
00E77B  1               ;       byte 1 = tile index
00E77B  1               ;       byte 2 = sprite attributes
00E77B  1               ;       byte 3 = relative X coordinate
00E77B  1               ;
00E77B  1               ; Destination:
00E77B  1               ;   OAM shadow buffer at $0200
00E77B  1               ;
00E77B  1               ; Coordinate adjustments:
00E77B  1               ;   destination Y = source Y + $38
00E77B  1               ;   destination X = source X + $36
00E77B  1               ;
00E77B  1               ; Exit:
00E77B  1               ;   $3F = updated OAM shadow write offset
00E77B  1               ;   $20 incremented after a nonempty sprite list
00E77B  1               ; ============================================================================
00E77B  1               
00E77B  1               ; ----------------------------------------------------------------------------
00E77B  1               ; Contract:
00E77B  1               ;   Description: Implements Render Sprite Record List.
00E77B  1               ;   Entry: Registers: A, X, Y; Memory: $0400, $0401, (indirectptrlo), oamwriteoffset, objectscreeny
00E77B  1               ;   Returns/products: Registers/clobbers: A, X, Y
00E77B  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E77B  1               ;   Memory effects: indirectptrlo, indirectptrhi, $04, $0200, oamwriteoffset
00E77B  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E77B  1               ;          comparison, load, or store path and are not a stable API product.
00E77B  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00E77B  1               ; ----------------------------------------------------------------------------
00E77B  1               RenderSpriteRecordList:         ; $E77B
00E77B  1  0A               asl                         ; $E77B: 0A
00E77C  1                                               ; Convert pointer index to byte offset.
00E77C  1               
00E77C  1  A8               tay                         ; $E77C: A8
00E77D  1               
00E77D  1               ; ----------------------------------------------------------------------------
00E77D  1               ; Load the selected little-endian source pointer from $0400.
00E77D  1               ; ----------------------------------------------------------------------------
00E77D  1               
00E77D  1  B9 00 04         lda $0400,y                 ; $E77D: B9 00 04
00E780  1  85 00            sta IndirectPtrLo           ; $E780: 85 00
00E782  1               
00E782  1  B9 01 04         lda $0401,y                 ; $E782: B9 01 04
00E785  1  85 01            sta IndirectPtrHi           ; $E785: 85 01
00E787  1               
00E787  1               ; ----------------------------------------------------------------------------
00E787  1               ; Read the sprite count.
00E787  1               ; ----------------------------------------------------------------------------
00E787  1               
00E787  1  A0 00            ldy #$00                    ; $E787: A0 00
00E789  1               
00E789  1  B1 00            lda (IndirectPtrLo),y       ; $E789: B1 00
00E78B  1  F0 2E            beq RenderSpriteRecordList_Return
00E78D  1                                               ; $E78B: F0 2E
00E78D  1               
00E78D  1  85 04            sta $04                     ; $E78D: 85 04
00E78F  1                                               ; Number of four-byte sprite records.
00E78F  1               
00E78F  1               ; ----------------------------------------------------------------------------
00E78F  1               ; Load the current OAM shadow write position.
00E78F  1               ; ----------------------------------------------------------------------------
00E78F  1               
00E78F  1  A6 3F            ldx OamWriteOffset          ; $E78F: A6 3F
00E791  1               
00E791  1               ; ----------------------------------------------------------------------------
00E791  1               ; Copy one sprite record.
00E791  1               ; ----------------------------------------------------------------------------
00E791  1               
00E791  1               RenderSpriteRecordList_Loop:    ; $E791
00E791  1  C8               iny                         ; $E791: C8
00E792  1               
00E792  1               ; ----------------------------------------------------------------------------
00E792  1               ; OAM byte 0: Y coordinate.
00E792  1               ; ----------------------------------------------------------------------------
00E792  1               
00E792  1  18               clc                         ; $E792: 18
00E793  1               
00E793  1  B1 00            lda (IndirectPtrLo),y       ; $E793: B1 00
00E795  1  65 38            adc ObjectScreenY           ; $E795: 65 38
00E797  1  9D 00 02         sta $0200,x                 ; $E797: 9D 00 02
00E79A  1               
00E79A  1  E8               inx                         ; $E79A: E8
00E79B  1  C8               iny                         ; $E79B: C8
00E79C  1               
00E79C  1               ; ----------------------------------------------------------------------------
00E79C  1               ; OAM byte 1: tile index.
00E79C  1               ; ----------------------------------------------------------------------------
00E79C  1               
00E79C  1  B1 00            lda (IndirectPtrLo),y       ; $E79C: B1 00
00E79E  1  9D 00 02         sta $0200,x                 ; $E79E: 9D 00 02
00E7A1  1               
00E7A1  1  E8               inx                         ; $E7A1: E8
00E7A2  1  C8               iny                         ; $E7A2: C8
00E7A3  1               
00E7A3  1               ; ----------------------------------------------------------------------------
00E7A3  1               ; OAM byte 2: sprite attributes.
00E7A3  1               ; ----------------------------------------------------------------------------
00E7A3  1               
00E7A3  1  B1 00            lda (IndirectPtrLo),y       ; $E7A3: B1 00
00E7A5  1  9D 00 02         sta $0200,x                 ; $E7A5: 9D 00 02
00E7A8  1               
00E7A8  1  E8               inx                         ; $E7A8: E8
00E7A9  1  C8               iny                         ; $E7A9: C8
00E7AA  1               
00E7AA  1               ; ----------------------------------------------------------------------------
00E7AA  1               ; OAM byte 3: X coordinate.
00E7AA  1               ; ----------------------------------------------------------------------------
00E7AA  1               
00E7AA  1  18               clc                         ; $E7AA: 18
00E7AB  1               
00E7AB  1  B1 00            lda (IndirectPtrLo),y       ; $E7AB: B1 00
00E7AD  1  65 36            adc ObjectScreenX           ; $E7AD: 65 36
00E7AF  1  9D 00 02         sta $0200,x                 ; $E7AF: 9D 00 02
00E7B2  1               
00E7B2  1  E8               inx                         ; $E7B2: E8
00E7B3  1               
00E7B3  1               ; ----------------------------------------------------------------------------
00E7B3  1               ; Continue until all sprite records are copied.
00E7B3  1               ; ----------------------------------------------------------------------------
00E7B3  1               
00E7B3  1  C6 04            dec $04                     ; $E7B3: C6 04
00E7B5  1  D0 DA            bne RenderSpriteRecordList_Loop
00E7B7  1                                               ; $E7B5: D0 DA
00E7B7  1               
00E7B7  1               ; ----------------------------------------------------------------------------
00E7B7  1               ; Save the updated OAM write offset and mark that another sprite group was
00E7B7  1               ; emitted.
00E7B7  1               ; ----------------------------------------------------------------------------
00E7B7  1               
00E7B7  1  86 3F            stx OamWriteOffset          ; $E7B7: 86 3F
00E7B9  1  E6 20            inc FrameState20            ; $E7B9: E6 20
00E7BB  1               
00E7BB  1               RenderSpriteRecordList_Return:  ; $E7BB
00E7BB  1  60               rts
00E7BC  1               ; ============================================================================
00E7BC  1               ; $E7BC-$E7CA
00E7BC  1               ; Hide a caller-selected number of sprites in the OAM shadow buffer.
00E7BC  1               ;
00E7BC  1               ; Entry:
00E7BC  1               ;   Y = number of sprites to hide
00E7BC  1               ;
00E7BC  1               ; Operation:
00E7BC  1               ;   Each OAM entry occupies four bytes:
00E7BC  1               ;
00E7BC  1               ;       byte 0 = Y coordinate
00E7BC  1               ;       byte 1 = tile
00E7BC  1               ;       byte 2 = attributes
00E7BC  1               ;       byte 3 = X coordinate
00E7BC  1               ;
00E7BC  1               ;   This routine writes $F0 to each sprite's Y coordinate, placing it below
00E7BC  1               ;   the visible screen, then advances X by four bytes to the next sprite.
00E7BC  1               ;
00E7BC  1               ; Note:
00E7BC  1               ;   The OAM write offset in $3F is read but not updated.
00E7BC  1               ; ============================================================================
00E7BC  1               
00E7BC  1               HideOamSprites:                 ; $E7BC
00E7BC  1  A6 3F            ldx OamWriteOffset          ; $E7BC: A6 3F
00E7BE  1                                               ; Start at the current OAM shadow offset.
00E7BE  1               
00E7BE  1  A9 F0            lda #$F0                    ; $E7BE: A9 F0
00E7C0  1                                               ; Off-screen Y coordinate.
00E7C0  1               
00E7C0  1               HideOamSprites_Loop:            ; $E7C0
00E7C0  1  9D 00 02         sta $0200,x                 ; $E7C0: 9D 00 02
00E7C3  1                                               ; Hide the current sprite.
00E7C3  1               
00E7C3  1  E8               inx                         ; $E7C3: E8
00E7C4  1  E8               inx                         ; $E7C4: E8
00E7C5  1  E8               inx                         ; $E7C5: E8
00E7C6  1  E8               inx                         ; $E7C6: E8
00E7C7  1                                               ; Advance to the next sprite's Y byte.
00E7C7  1               
00E7C7  1  88               dey                         ; $E7C7: 88
00E7C8  1  D0 F6            bne HideOamSprites_Loop     ; $E7C8: D0 F6
00E7CA  1               
00E7CA  1  60               rts                         ; $E7CA: 60
00E7CB  1               
00E7CB  1               ; ============================================================================
00E7CB  1               ; $E7CB-$E7DA
00E7CB  1               ; Convert a signed 16-bit value in A:Y to its absolute magnitude.
00E7CB  1               ;
00E7CB  1               ; Entry:
00E7CB  1               ;   A = signed high byte
00E7CB  1               ;   Y = low byte
00E7CB  1               ;
00E7CB  1               ; Exit:
00E7CB  1               ;   A:Y = absolute magnitude
00E7CB  1               ;
00E7CB  1               ; If A is nonnegative, the value is returned unchanged. Otherwise, the
00E7CB  1               ; complete 16-bit pair is negated using one's complement plus one.
00E7CB  1               ; ============================================================================
00E7CB  1               
00E7CB  1               ; ----------------------------------------------------------------------------
00E7CB  1               ; Contract:
00E7CB  1               ;   Description: Implements Absolute Value A Y.
00E7CB  1               ;   Entry: Registers: A, Y
00E7CB  1               ;   Returns/products: Registers/clobbers: A, Y; Flags: condition flags may carry result state
00E7CB  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E7CB  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00E7CB  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E7CB  1               ;          comparison, load, or store path and are not a stable API product.
00E7CB  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 6.
00E7CB  1               ; ----------------------------------------------------------------------------
00E7CB  1               AbsoluteValueAY:                ; $E7CB
00E7CB  1  10 0D            bpl AbsoluteValueAY_Return  ; $E7CB: 10 0D
00E7CD  1               
00E7CD  1               ; ----------------------------------------------------------------------------
00E7CD  1               ; Negate the high byte and preserve it while processing the low byte.
00E7CD  1               ; ----------------------------------------------------------------------------
00E7CD  1               
00E7CD  1  49 FF            eor #$FF                    ; $E7CD: 49 FF
00E7CF  1  48               pha                         ; $E7CF: 48
00E7D0  1               
00E7D0  1               ; ----------------------------------------------------------------------------
00E7D0  1               ; Negate the low byte.
00E7D0  1               ;
00E7D0  1               ; SEC followed by ADC #$00 adds one to the complemented byte.
00E7D0  1               ; ----------------------------------------------------------------------------
00E7D0  1               
00E7D0  1  98               tya                         ; $E7D0: 98
00E7D1  1  49 FF            eor #$FF                    ; $E7D1: 49 FF
00E7D3  1               
00E7D3  1  38               sec                         ; $E7D3: 38
00E7D4  1  69 00            adc #$00                    ; $E7D4: 69 00
00E7D6  1  A8               tay                         ; $E7D6: A8
00E7D7  1               
00E7D7  1               ; ----------------------------------------------------------------------------
00E7D7  1               ; Restore the complemented high byte and propagate carry from the low-byte
00E7D7  1               ; negation.
00E7D7  1               ; ----------------------------------------------------------------------------
00E7D7  1               
00E7D7  1  68               pla                         ; $E7D7: 68
00E7D8  1  69 00            adc #$00                    ; $E7D8: 69 00
00E7DA  1               
00E7DA  1               AbsoluteValueAY_Return:         ; $E7DA
00E7DA  1  60               rts                         ; $E7DA: 60
00E7DB  1               
00E7DB  1               ; ============================================================================
00E7DB  1               ; $E7DB-$E7F4
00E7DB  1               ; Calculate an eight-bit scaled product.
00E7DB  1               ;
00E7DB  1               ; Entry:
00E7DB  1               ;   A = multiplicand/value
00E7DB  1               ;   X = scale or shift count plus one
00E7DB  1               ;
00E7DB  1               ; Operation:
00E7DB  1               ;   X is decremented once and saved in $2B. The routine then performs eight
00E7DB  1               ;   shift-and-add rounds using $28 as the high/result byte.
00E7DB  1               ;
00E7DB  1               ; Exit:
00E7DB  1               ;   A = result low byte
00E7DB  1               ;   X = result high byte from $28
00E7DB  1               ; ============================================================================
00E7DB  1               
00E7DB  1               ; ----------------------------------------------------------------------------
00E7DB  1               ; Contract:
00E7DB  1               ;   Description: Calculates Scaled Product.
00E7DB  1               ;   Entry: Registers: A, X; Memory: $2b, $28
00E7DB  1               ;   Returns/products: Registers/clobbers: A, X
00E7DB  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E7DB  1               ;   Memory effects: $2b, $28
00E7DB  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E7DB  1               ;          comparison, load, or store path and are not a stable API product.
00E7DB  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00E7DB  1               ; ----------------------------------------------------------------------------
00E7DB  1               CalculateScaledProduct:         ; $E7DB
00E7DB  1  CA               dex                         ; $E7DB: CA
00E7DC  1  86 2B            stx $2B                     ; $E7DC: 86 2B
00E7DE  1               
00E7DE  1  85 28            sta $28                     ; $E7DE: 85 28
00E7E0  1               
00E7E0  1  A9 00            lda #$00                    ; $E7E0: A9 00
00E7E2  1  A2 08            ldx #$08                    ; $E7E2: A2 08
00E7E4  1               
00E7E4  1               ; ----------------------------------------------------------------------------
00E7E4  1               ; Shift the 16-bit A:$28 result left.
00E7E4  1               ;
00E7E4  1               ; Whenever carry is set after rotating $28, add the saved scale value from
00E7E4  1               ; $2B. Carry from that addition increments $28.
00E7E4  1               ; ----------------------------------------------------------------------------
00E7E4  1               
00E7E4  1               CalculateScaledProduct_Loop:    ; $E7E4
00E7E4  1  0A               asl                         ; $E7E4: 0A
00E7E5  1  26 28            rol $28                     ; $E7E5: 26 28
00E7E7  1               
00E7E7  1  90 06            bcc CalculateScaledProduct_Next
00E7E9  1                                               ; $E7E7: 90 06
00E7E9  1               
00E7E9  1  65 2B            adc $2B                     ; $E7E9: 65 2B
00E7EB  1  90 02            bcc CalculateScaledProduct_Next
00E7ED  1                                               ; $E7EB: 90 02
00E7ED  1               
00E7ED  1  E6 28            inc $28                     ; $E7ED: E6 28
00E7EF  1               
00E7EF  1               CalculateScaledProduct_Next:    ; $E7EF
00E7EF  1  CA               dex                         ; $E7EF: CA
00E7F0  1  D0 F2            bne CalculateScaledProduct_Loop
00E7F2  1                                               ; $E7F0: D0 F2
00E7F2  1               
00E7F2  1  A6 28            ldx $28                     ; $E7F2: A6 28
00E7F4  1  60               rts                         ; $E7F4: 60
00E7F5  1               
00E7F5  1               ; ============================================================================
00E7F5  1               ; $E7F5-$E80A
00E7F5  1               ; Perform a nine-round restoring division.
00E7F5  1               ;
00E7F5  1               ; Entry:
00E7F5  1               ;   A = dividend
00E7F5  1               ;   Y = divisor
00E7F5  1               ;   X = initial high or remainder byte
00E7F5  1               ;
00E7F5  1               ; Working storage:
00E7F5  1               ;   $28 = quotient/result shift register
00E7F5  1               ;   $2B = divisor
00E7F5  1               ;
00E7F5  1               ; Exit:
00E7F5  1               ;   A = quotient/result byte from $28
00E7F5  1               ;
00E7F5  1               ; Each round conditionally subtracts the divisor, then rotates the result bit
00E7F5  1               ; into $28.
00E7F5  1               ; ============================================================================
00E7F5  1               
00E7F5  1               ; ----------------------------------------------------------------------------
00E7F5  1               ; Contract:
00E7F5  1               ;   Description: Implements Divide Unsigned Byte.
00E7F5  1               ;   Entry: Registers: A, X, Y; Memory: $2b, $28
00E7F5  1               ;   Returns/products: Registers/clobbers: A, X
00E7F5  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E7F5  1               ;   Memory effects: $28, $2b
00E7F5  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E7F5  1               ;          comparison, load, or store path and are not a stable API product.
00E7F5  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00E7F5  1               ; ----------------------------------------------------------------------------
00E7F5  1               DivideUnsignedByte:             ; $E7F5
00E7F5  1  85 28            sta $28                     ; $E7F5: 85 28
00E7F7  1  84 2B            sty $2B                     ; $E7F7: 84 2B
00E7F9  1               
00E7F9  1  8A               txa                         ; $E7F9: 8A
00E7FA  1               
00E7FA  1  A2 09            ldx #$09                    ; $E7FA: A2 09
00E7FC  1               
00E7FC  1               DivideUnsignedByte_Loop:        ; $E7FC
00E7FC  1  C5 2B            cmp $2B                     ; $E7FC: C5 2B
00E7FE  1  90 02            bcc DivideUnsignedByte_Shift
00E800  1                                               ; $E7FE: 90 02
00E800  1               
00E800  1  E5 2B            sbc $2B                     ; $E800: E5 2B
00E802  1               
00E802  1               DivideUnsignedByte_Shift:       ; $E802
00E802  1  26 28            rol $28                     ; $E802: 26 28
00E804  1  2A               rol                         ; $E804: 2A
00E805  1               
00E805  1  CA               dex                         ; $E805: CA
00E806  1  D0 F4            bne DivideUnsignedByte_Loop ; $E806: D0 F4
00E808  1               
00E808  1  A5 28            lda $28                     ; $E808: A5 28
00E80A  1  60               rts                         ; $E80A: 60
00E80B  1               
00E80B  1               ; ============================================================================
00E80B  1               ; $E80B-$E821
00E80B  1               ; Initialize an eight-round vector or magnitude calculation.
00E80B  1               ;
00E80B  1               ; Entry:
00E80B  1               ;   X = signed horizontal input
00E80B  1               ;   Y = vertical input
00E80B  1               ;
00E80B  1               ; Working state:
00E80B  1               ;   $D4 = absolute or complemented horizontal input
00E80B  1               ;   $D5 = vertical input
00E80B  1               ;   $DB = round/shift state, initialized to $FF and then incremented to zero
00E80B  1               ;
00E80B  1               ; Exit:
00E80B  1               ;   Result is returned by the state accumulated through $E8DA.
00E80B  1               ;
00E80B  1               ; The precise mathematical operation depends on the helper at $E8DA, but this
00E80B  1               ; routine clearly normalizes the sign of X and performs eight identical rounds.
00E80B  1               ; ============================================================================
00E80B  1               
00E80B  1               ; ----------------------------------------------------------------------------
00E80B  1               ; Contract:
00E80B  1               ;   Description: Calculates Vector Magnitude.
00E80B  1               ;   Entry: Registers: A, X, Y
00E80B  1               ;   Returns/products: Registers/clobbers: A, X, Y
00E80B  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E80B  1               ;   Memory effects: $d4, $d5, $db
00E80B  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E80B  1               ;          comparison, load, or store path and are not a stable API product.
00E80B  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00E80B  1               ; ----------------------------------------------------------------------------
00E80B  1               CalculateVectorMagnitude:       ; $E80B
00E80B  1  8A               txa                         ; $E80B: 8A
00E80C  1  10 02            bpl CalculateVectorMagnitude_SaveX
00E80E  1                                               ; $E80C: 10 02
00E80E  1               
00E80E  1               ; ----------------------------------------------------------------------------
00E80E  1               ; Convert a negative X input using one's complement.
00E80E  1               ;
00E80E  1               ; Unlike a full absolute-value conversion, this does not add one here. The
00E80E  1               ; lower-level iterative helper accounts for the representation.
00E80E  1               ; ----------------------------------------------------------------------------
00E80E  1               
00E80E  1  49 FF            eor #$FF                    ; $E80E: 49 FF
00E810  1               
00E810  1               CalculateVectorMagnitude_SaveX: ; $E810
00E810  1  85 D4            sta $D4                     ; $E810: 85 D4
00E812  1  84 D5            sty $D5                     ; $E812: 84 D5
00E814  1               
00E814  1               ; ----------------------------------------------------------------------------
00E814  1               ; Initialize the round state.
00E814  1               ;
00E814  1               ; X is first set to $FF and stored in $DB, then incremented to zero before the
00E814  1               ; eight processing rounds begin.
00E814  1               ; ----------------------------------------------------------------------------
00E814  1               
00E814  1  A2 FF            ldx #$FF                    ; $E814: A2 FF
00E816  1  86 DB            stx $DB                     ; $E816: 86 DB
00E818  1               
00E818  1  E8               inx                         ; $E818: E8
00E819  1                                               ; X = $00.
00E819  1               
00E819  1  A0 08            ldy #$08                    ; $E819: A0 08
00E81B  1               
00E81B  1               CalculateVectorMagnitude_Loop:  ; $E81B
00E81B  1  20 DA E8         jsr UpdatePrimaryArithmeticPair                   ; $E81B: 20 DA E8
00E81E  1               
00E81E  1  88               dey                         ; $E81E: 88
00E81F  1  D0 FA            bne CalculateVectorMagnitude_Loop
00E821  1                                               ; $E81F: D0 FA
00E821  1               
00E821  1  60               rts                         ; $E821: 60
00E822  1               
00E822  1               ; ============================================================================
00E822  1               ; $E822-$E854
00E822  1               ; Initialize and run a signed two-component vector calculation.
00E822  1               ;
00E822  1               ; Entry:
00E822  1               ;   A = first result or vector component
00E822  1               ;   X = signed horizontal component
00E822  1               ;   Y = vertical component
00E822  1               ;
00E822  1               ; Working state:
00E822  1               ;   $D4/$D5 = normalized signed source pair
00E822  1               ;   $D6/$D7 = result or secondary pair
00E822  1               ;   $D9     = sign-extension byte, $00 or $FF
00E822  1               ;   $DB     = round/shift state
00E822  1               ;
00E822  1               ; Exit:
00E822  1               ;   A = $D9 XOR $D6
00E822  1               ;   Y = $D9 XOR $D7
00E822  1               ;
00E822  1               ; The routine performs eight rounds using both $E8DA and $E908, then applies
00E822  1               ; the original sign extension to the result pair.
00E822  1               ; ============================================================================
00E822  1               
00E822  1               CalculateSignedVector:          ; $E822
00E822  1  85 D6            sta $D6                     ; $E822: 85 D6
00E824  1               
00E824  1  A9 00            lda #$00                    ; $E824: A9 00
00E826  1  85 D7            sta $D7                     ; $E826: 85 D7
00E828  1               
00E828  1               ; ----------------------------------------------------------------------------
00E828  1               ; Alternate entry used by callers that have already initialized $D6/$D7.
00E828  1               ;
00E828  1               ; Entry:
00E828  1               ;   X = signed horizontal component
00E828  1               ;   Y = vertical component
00E828  1               ; ----------------------------------------------------------------------------
00E828  1               
00E828  1               CalculateSignedVectorFromResult: ; $E828
00E828  1  84 D5            sty $D5                     ; $E828: 84 D5
00E82A  1               
00E82A  1  A0 00            ldy #$00                    ; $E82A: A0 00
00E82C  1                                               ; Default sign-extension byte.
00E82C  1               
00E82C  1  8A               txa                         ; $E82C: 8A
00E82D  1  10 03            bpl CalculateSignedVector_SaveSign
00E82F  1                                               ; $E82D: 10 03
00E82F  1               
00E82F  1               ; ----------------------------------------------------------------------------
00E82F  1               ; Normalize a negative X component using one's complement and set the sign
00E82F  1               ; extension byte to $FF.
00E82F  1               ; ----------------------------------------------------------------------------
00E82F  1               
00E82F  1  49 FF            eor #$FF                    ; $E82F: 49 FF
00E831  1  88               dey                         ; $E831: 88
00E832  1                                               ; Y = $FF.
00E832  1               
00E832  1               CalculateSignedVector_SaveSign: ; $E832
00E832  1  84 D9            sty $D9                     ; $E832: 84 D9
00E834  1  85 D4            sta $D4                     ; $E834: 85 D4
00E836  1               
00E836  1               ; ----------------------------------------------------------------------------
00E836  1               ; Apply the sign extension to the vertical source component.
00E836  1               ; ----------------------------------------------------------------------------
00E836  1               
00E836  1  98               tya                         ; $E836: 98
00E837  1  45 D5            eor $D5                     ; $E837: 45 D5
00E839  1  85 D5            sta $D5                     ; $E839: 85 D5
00E83B  1               
00E83B  1               ; ----------------------------------------------------------------------------
00E83B  1               ; Initialize the round state.
00E83B  1               ; ----------------------------------------------------------------------------
00E83B  1               
00E83B  1  A2 FF            ldx #$FF                    ; $E83B: A2 FF
00E83D  1  86 DB            stx $DB                     ; $E83D: 86 DB
00E83F  1               
00E83F  1  E8               inx                         ; $E83F: E8
00E840  1                                               ; X = $00.
00E840  1               
00E840  1  A0 08            ldy #$08                    ; $E840: A0 08
00E842  1               
00E842  1               ; ----------------------------------------------------------------------------
00E842  1               ; Run eight rounds. Each round performs the common step at $E8DA followed by
00E842  1               ; the signed-result accumulation step at $E908.
00E842  1               ; ----------------------------------------------------------------------------
00E842  1               
00E842  1               CalculateSignedVector_Loop:     ; $E842
00E842  1  20 DA E8         jsr UpdatePrimaryArithmeticPair                   ; $E842: 20 DA E8
00E845  1  20 08 E9         jsr UpdateSecondaryArithmeticPair                   ; $E845: 20 08 E9
00E848  1               
00E848  1  88               dey                         ; $E848: 88
00E849  1  D0 F7            bne CalculateSignedVector_Loop
00E84B  1                                               ; $E849: D0 F7
00E84B  1               
00E84B  1               ; ----------------------------------------------------------------------------
00E84B  1               ; Apply the original sign extension to the resulting pair.
00E84B  1               ; ----------------------------------------------------------------------------
00E84B  1               
00E84B  1  A5 D9            lda $D9                     ; $E84B: A5 D9
00E84D  1  45 D7            eor $D7                     ; $E84D: 45 D7
00E84F  1  A8               tay                         ; $E84F: A8
00E850  1               
00E850  1  A5 D9            lda $D9                     ; $E850: A5 D9
00E852  1  45 D6            eor $D6                     ; $E852: 45 D6
00E854  1               
00E854  1  60               rts                         ; $E854: 60
00E855  1               
00E855  1               ; ============================================================================
00E855  1               ; $E855-$E876
00E855  1               ; Run an eight-round signed vector calculation using a caller-supplied result
00E855  1               ; pair in X:Y.
00E855  1               ;
00E855  1               ; Entry:
00E855  1               ;   A = signed/control input, transformed by XOR #$80
00E855  1               ;   X = first result component
00E855  1               ;   Y = second result component
00E855  1               ;
00E855  1               ; Working state:
00E855  1               ;   $D8 = transformed input shift register
00E855  1               ;   $D6 = saved X component
00E855  1               ;   $D7 = saved Y component
00E855  1               ;   $DA = per-round sign or mask byte
00E855  1               ;   $DB = round index, progressing from $00 through $07
00E855  1               ;
00E855  1               ; Exit:
00E855  1               ;   A = value left by the final $E908 call
00E855  1               ;   Y = original input Y component
00E855  1               ; ============================================================================
00E855  1               
00E855  1               ; ----------------------------------------------------------------------------
00E855  1               ; Contract:
00E855  1               ;   Description: Calculates Vector From Rotated Mask.
00E855  1               ;   Entry: Registers: A, X, Y; Memory: $d7
00E855  1               ;   Returns/products: Registers/clobbers: A, X, Y
00E855  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E855  1               ;   Memory effects: $d8, $d6, $d7, $db, $da
00E855  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E855  1               ;          comparison, load, or store path and are not a stable API product.
00E855  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 2.
00E855  1               ; ----------------------------------------------------------------------------
00E855  1               CalculateVectorFromRotatedMask: ; $E855
00E855  1  49 80            eor #$80                    ; $E855: 49 80
00E857  1  85 D8            sta $D8                     ; $E857: 85 D8
00E859  1               
00E859  1  86 D6            stx $D6                     ; $E859: 86 D6
00E85B  1  84 D7            sty $D7                     ; $E85B: 84 D7
00E85D  1               
00E85D  1               ; ----------------------------------------------------------------------------
00E85D  1               ; Initialize the round index to $FF. It is incremented at the start of each
00E85D  1               ; round, producing indices $00-$07.
00E85D  1               ; ----------------------------------------------------------------------------
00E85D  1               
00E85D  1  A9 FF            lda #$FF                    ; $E85D: A9 FF
00E85F  1  85 DB            sta $DB                     ; $E85F: 85 DB
00E861  1               
00E861  1  A0 08            ldy #$08                    ; $E861: A0 08
00E863  1               
00E863  1               CalculateVectorFromRotatedMask_Loop: ; $E863
00E863  1  E6 DB            inc $DB                     ; $E863: E6 DB
00E865  1               
00E865  1               ; ----------------------------------------------------------------------------
00E865  1               ; Shift the next bit from $D8 into carry.
00E865  1               ;
00E865  1               ; X becomes:
00E865  1               ;   $00 when carry is clear
00E865  1               ;   $FF when carry is set
00E865  1               ;
00E865  1               ; This creates a sign-extension or conditional-mask byte in $DA.
00E865  1               ; ----------------------------------------------------------------------------
00E865  1               
00E865  1  A2 00            ldx #$00                    ; $E865: A2 00
00E867  1               
00E867  1  26 D8            rol $D8                     ; $E867: 26 D8
00E869  1  90 01            bcc CalculateVectorFromRotatedMask_SaveMask
00E86B  1                                               ; $E869: 90 01
00E86B  1               
00E86B  1  CA               dex                         ; $E86B: CA
00E86C  1                                               ; X = $FF.
00E86C  1               
00E86C  1               CalculateVectorFromRotatedMask_SaveMask: ; $E86C
00E86C  1  86 DA            stx $DA                     ; $E86C: 86 DA
00E86E  1               
00E86E  1               ; ----------------------------------------------------------------------------
00E86E  1               ; Apply the per-round result update.
00E86E  1               ; ----------------------------------------------------------------------------
00E86E  1               
00E86E  1  20 08 E9         jsr UpdateSecondaryArithmeticPair                   ; $E86E: 20 08 E9
00E871  1               
00E871  1  88               dey                         ; $E871: 88
00E872  1  D0 EF            bne CalculateVectorFromRotatedMask_Loop
00E874  1                                               ; $E872: D0 EF
00E874  1               
00E874  1               ; ----------------------------------------------------------------------------
00E874  1               ; Restore the original Y component before returning.
00E874  1               ; ----------------------------------------------------------------------------
00E874  1               
00E874  1  A4 D7            ldy $D7                     ; $E874: A4 D7
00E876  1  60               rts                         ; $E876: 60
00E877  1               
00E877  1               ; ============================================================================
00E877  1               ; $E877-$E8A4
00E877  1               ; Run an eight-round signed-vector normalization using source values in
00E877  1               ; $D4-$D7.
00E877  1               ;
00E877  1               ; Entry:
00E877  1               ;   $D4 = signed primary source component
00E877  1               ;   $D5 = secondary source component
00E877  1               ;   $D6/$D7 = result or destination pair
00E877  1               ;
00E877  1               ; Working state:
00E877  1               ;   $D9 = sign-extension byte derived from $D4
00E877  1               ;   $DA = per-round working mask/result
00E877  1               ;   $DB = shift/round state, initialized to $FF
00E877  1               ;
00E877  1               ; Exit:
00E877  1               ;   A = normalized first result component
00E877  1               ;   X = complemented sign-extension byte
00E877  1               ;   Y = normalized second result component
00E877  1               ; ============================================================================
00E877  1               
00E877  1               ; ----------------------------------------------------------------------------
00E877  1               ; Contract:
00E877  1               ;   Description: Implements Normalize Signed Vector.
00E877  1               ;   Entry: Registers: A, X, Y; Memory: $d4, $da, $d9, $d7, $d6
00E877  1               ;   Returns/products: Registers/clobbers: A, X, Y
00E877  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E877  1               ;   Memory effects: $db, $d9, $d4, $da
00E877  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E877  1               ;          comparison, load, or store path and are not a stable API product.
00E877  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00E877  1               ; ----------------------------------------------------------------------------
00E877  1               NormalizeSignedVector:          ; $E877
00E877  1  A0 FF            ldy #$FF                    ; $E877: A0 FF
00E879  1  84 DB            sty $DB                     ; $E879: 84 DB
00E87B  1               
00E87B  1               ; ----------------------------------------------------------------------------
00E87B  1               ; Normalize the signed source byte at $D4.
00E87B  1               ;
00E87B  1               ; For a nonnegative value:
00E87B  1               ;   $D9 = $FF
00E87B  1               ;   $D4 remains unchanged
00E87B  1               ;
00E87B  1               ; For a negative value:
00E87B  1               ;   $D9 = $00
00E87B  1               ;   $D4 is one's-complemented
00E87B  1               ; ----------------------------------------------------------------------------
00E87B  1               
00E87B  1  A5 D4            lda $D4                     ; $E87B: A5 D4
00E87D  1  10 03            bpl NormalizeSignedVector_SaveSign
00E87F  1                                               ; $E87D: 10 03
00E87F  1               
00E87F  1  C8               iny                         ; $E87F: C8
00E880  1                                               ; Y changes from $FF to $00.
00E880  1               
00E880  1  49 FF            eor #$FF                    ; $E880: 49 FF
00E882  1               
00E882  1               NormalizeSignedVector_SaveSign: ; $E882
00E882  1  84 D9            sty $D9                     ; $E882: 84 D9
00E884  1  85 D4            sta $D4                     ; $E884: 85 D4
00E886  1               
00E886  1               ; ----------------------------------------------------------------------------
00E886  1               ; Initialize X to zero and perform eight processing rounds.
00E886  1               ; ----------------------------------------------------------------------------
00E886  1               
00E886  1  A2 00            ldx #$00                    ; $E886: A2 00
00E888  1  A0 08            ldy #$08                    ; $E888: A0 08
00E88A  1               
00E88A  1               NormalizeSignedVector_Loop:     ; $E88A
00E88A  1  20 DA E8         jsr UpdatePrimaryArithmeticPair                   ; $E88A: 20 DA E8
00E88D  1               
00E88D  1               ; ----------------------------------------------------------------------------
00E88D  1               ; Apply the saved sign extension to $DA before updating the result pair.
00E88D  1               ; ----------------------------------------------------------------------------
00E88D  1               
00E88D  1  A5 DA            lda $DA                     ; $E88D: A5 DA
00E88F  1  45 D9            eor $D9                     ; $E88F: 45 D9
00E891  1  85 DA            sta $DA                     ; $E891: 85 DA
00E893  1               
00E893  1  20 08 E9         jsr UpdateSecondaryArithmeticPair                   ; $E893: 20 08 E9
00E896  1               
00E896  1  88               dey                         ; $E896: 88
00E897  1  D0 F1            bne NormalizeSignedVector_Loop
00E899  1                                               ; $E897: D0 F1
00E899  1               
00E899  1               ; ----------------------------------------------------------------------------
00E899  1               ; Apply the final sign correction to the output pair.
00E899  1               ; ----------------------------------------------------------------------------
00E899  1               
00E899  1  A5 D9            lda $D9                     ; $E899: A5 D9
00E89B  1  49 FF            eor #$FF                    ; $E89B: 49 FF
00E89D  1  AA               tax                         ; $E89D: AA
00E89E  1                                               ; X = complement of sign-extension byte.
00E89E  1               
00E89E  1  45 D7            eor $D7                     ; $E89E: 45 D7
00E8A0  1  A8               tay                         ; $E8A0: A8
00E8A1  1               
00E8A1  1  8A               txa                         ; $E8A1: 8A
00E8A2  1  45 D6            eor $D6                     ; $E8A2: 45 D6
00E8A4  1               
00E8A4  1  60               rts                         ; $E8A4: 60
00E8A5  1               
00E8A5  1               ; ============================================================================
00E8A5  1               ; $E8A5-$E8B6
00E8A5  1               ; Run an eight-round arithmetic transformation using the input pair X:Y.
00E8A5  1               ;
00E8A5  1               ; Entry:
00E8A5  1               ;   X = first input component
00E8A5  1               ;   Y = second input component
00E8A5  1               ;
00E8A5  1               ; Working state:
00E8A5  1               ;   $D4 = saved X component
00E8A5  1               ;   $D5 = saved Y component
00E8A5  1               ;   $DB = round state, initialized to $FF
00E8A5  1               ;
00E8A5  1               ; Exit:
00E8A5  1               ;   Result is returned in the state/registers produced by the final call to
00E8A5  1               ;   $E931.
00E8A5  1               ;
00E8A5  1               ; The exact mathematical role depends on the shared helper at $E931, but this
00E8A5  1               ; routine is clearly an eight-round wrapper around that operation.
00E8A5  1               ; ============================================================================
00E8A5  1               
00E8A5  1               ; ----------------------------------------------------------------------------
00E8A5  1               ; Contract:
00E8A5  1               ;   Description: Runs Eight Round Transform.
00E8A5  1               ;   Entry: Registers: X, Y
00E8A5  1               ;   Returns/products: Registers/clobbers: X, Y
00E8A5  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E8A5  1               ;   Memory effects: $d4, $d5, $db
00E8A5  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E8A5  1               ;          comparison, load, or store path and are not a stable API product.
00E8A5  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00E8A5  1               ; ----------------------------------------------------------------------------
00E8A5  1               RunEightRoundTransform:         ; $E8A5
00E8A5  1  86 D4            stx $D4                     ; $E8A5: 86 D4
00E8A7  1  84 D5            sty $D5                     ; $E8A7: 84 D5
00E8A9  1               
00E8A9  1               ; ----------------------------------------------------------------------------
00E8A9  1               ; Initialize the round state.
00E8A9  1               ;
00E8A9  1               ; X is first set to $FF and stored in $DB, then incremented to zero.
00E8A9  1               ; ----------------------------------------------------------------------------
00E8A9  1               
00E8A9  1  A2 FF            ldx #$FF                    ; $E8A9: A2 FF
00E8AB  1  86 DB            stx $DB                     ; $E8AB: 86 DB
00E8AD  1               
00E8AD  1  E8               inx                         ; $E8AD: E8
00E8AE  1                                               ; X = $00.
00E8AE  1               
00E8AE  1  A0 08            ldy #$08                    ; $E8AE: A0 08
00E8B0  1               
00E8B0  1               RunEightRoundTransform_Loop:    ; $E8B0
00E8B0  1  20 31 E9         jsr UpdatePrimaryArithmeticPairAlternate                   ; $E8B0: 20 31 E9
00E8B3  1               
00E8B3  1  88               dey                         ; $E8B3: 88
00E8B4  1  D0 FA            bne RunEightRoundTransform_Loop
00E8B6  1                                               ; $E8B4: D0 FA
00E8B6  1               
00E8B6  1  60               rts                         ; $E8B6: 60
00E8B7  1               
00E8B7  1               ; ============================================================================
00E8B7  1               ; $E8B7-$E8D9
00E8B7  1               ; Convert the A:Y input pair to component magnitudes, perform eight common
00E8B7  1               ; arithmetic rounds, and return a transformed high/result byte.
00E8B7  1               ;
00E8B7  1               ; Entry:
00E8B7  1               ;   A = first signed component
00E8B7  1               ;   Y = second signed component
00E8B7  1               ;
00E8B7  1               ; Normalization:
00E8B7  1               ;   Negative components are one's-complemented.
00E8B7  1               ;
00E8B7  1               ; Working state:
00E8B7  1               ;   $D4 = normalized first component
00E8B7  1               ;   $D5 = normalized second component
00E8B7  1               ;   $D9/$DA = common round result pair
00E8B7  1               ;   $DB = round state, initialized to $FF
00E8B7  1               ;
00E8B7  1               ; Exit:
00E8B7  1               ;   A = $D9 XOR $7F
00E8B7  1               ;
00E8B7  1               ; This is not a standard two's-complement absolute-value conversion because no
00E8B7  1               ; one is added after the complement. The shared round helper accounts for the
00E8B7  1               ; representation.
00E8B7  1               ; ============================================================================
00E8B7  1               
00E8B7  1               TransformSignedComponentPair:   ; $E8B7
00E8B7  1  10 02            bpl TransformSignedComponentPair_SaveA
00E8B9  1                                               ; $E8B7: 10 02
00E8B9  1               
00E8B9  1  49 FF            eor #$FF                    ; $E8B9: 49 FF
00E8BB  1               
00E8BB  1               TransformSignedComponentPair_SaveA: ; $E8BB
00E8BB  1  85 D4            sta $D4                     ; $E8BB: 85 D4
00E8BD  1               
00E8BD  1               ; ----------------------------------------------------------------------------
00E8BD  1               ; Normalize the Y component.
00E8BD  1               ; ----------------------------------------------------------------------------
00E8BD  1               
00E8BD  1  98               tya                         ; $E8BD: 98
00E8BE  1  10 02            bpl TransformSignedComponentPair_SaveY
00E8C0  1                                               ; $E8BE: 10 02
00E8C0  1               
00E8C0  1  49 FF            eor #$FF                    ; $E8C0: 49 FF
00E8C2  1               
00E8C2  1               TransformSignedComponentPair_SaveY: ; $E8C2
00E8C2  1  85 D5            sta $D5                     ; $E8C2: 85 D5
00E8C4  1               
00E8C4  1               ; ----------------------------------------------------------------------------
00E8C4  1               ; Initialize the round state.
00E8C4  1               ; ----------------------------------------------------------------------------
00E8C4  1               
00E8C4  1  A2 FF            ldx #$FF                    ; $E8C4: A2 FF
00E8C6  1  86 DB            stx $DB                     ; $E8C6: 86 DB
00E8C8  1               
00E8C8  1  E8               inx                         ; $E8C8: E8
00E8C9  1                                               ; X = $00.
00E8C9  1               
00E8C9  1  A0 08            ldy #$08                    ; $E8C9: A0 08
00E8CB  1               
00E8CB  1               ; ----------------------------------------------------------------------------
00E8CB  1               ; Run eight common arithmetic rounds.
00E8CB  1               ;
00E8CB  1               ; After each round:
00E8CB  1               ;   $DA is shifted left.
00E8CB  1               ;   Carry is rotated into $D9.
00E8CB  1               ; ----------------------------------------------------------------------------
00E8CB  1               
00E8CB  1               TransformSignedComponentPair_Loop: ; $E8CB
00E8CB  1  20 DA E8         jsr UpdatePrimaryArithmeticPair                   ; $E8CB: 20 DA E8
00E8CE  1               
00E8CE  1  06 DA            asl $DA                     ; $E8CE: 06 DA
00E8D0  1  26 D9            rol $D9                     ; $E8D0: 26 D9
00E8D2  1               
00E8D2  1  88               dey                         ; $E8D2: 88
00E8D3  1  D0 F6            bne TransformSignedComponentPair_Loop
00E8D5  1                                               ; $E8D3: D0 F6
00E8D5  1               
00E8D5  1               ; ----------------------------------------------------------------------------
00E8D5  1               ; Return the transformed result.
00E8D5  1               ; ----------------------------------------------------------------------------
00E8D5  1               
00E8D5  1  A5 D9            lda $D9                     ; $E8D5: A5 D9
00E8D7  1  49 7F            eor #$7F                    ; $E8D7: 49 7F
00E8D9  1               
00E8D9  1  60               rts                         ; $E8D9: 60
00E8DA  1               
00E8DA  1               ; ============================================================================
00E8DA  1               ; $E8DA-$E907
00E8DA  1               ; Shared per-round arithmetic update for source pair $D4/$D5.
00E8DA  1               ;
00E8DA  1               ; Working state:
00E8DA  1               ;   $D4/$D5 = signed or fixed-point accumulator
00E8DA  1               ;   $DA     = per-round sign/mask byte
00E8DA  1               ;   $DB     = shift count, incremented at the start of the round
00E8DA  1               ;
00E8DA  1               ; Operation:
00E8DA  1               ;   1. Increment the shift count.
00E8DA  1               ;   2. Derive $DA from the sign of $D5.
00E8DA  1               ;   3. Shift and add $D4 into itself.
00E8DA  1               ;   4. Shift a sign-corrected form of $D4.
00E8DA  1               ;   5. Add the result into $D5.
00E8DA  1               ;
00E8DA  1               ; Exit:
00E8DA  1               ;   $D4/$D5 updated in place
00E8DA  1               ; ============================================================================
00E8DA  1               
00E8DA  1               ; ----------------------------------------------------------------------------
00E8DA  1               ; Contract:
00E8DA  1               ;   Description: Updates Primary Arithmetic Pair.
00E8DA  1               ;   Entry: Registers: A, X; Memory: $d5, $db, $d4, $da
00E8DA  1               ;   Returns/products: Registers/clobbers: A, X
00E8DA  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E8DA  1               ;   Memory effects: $da, $d5, $d4
00E8DA  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E8DA  1               ;          comparison, load, or store path and are not a stable API product.
00E8DA  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 4.
00E8DA  1               ; ----------------------------------------------------------------------------
00E8DA  1               UpdatePrimaryArithmeticPair:    ; $E8DA
00E8DA  1  E6 DB            inc $DB                     ; $E8DA: E6 DB
00E8DC  1                                               ; Advance the per-round shift count.
00E8DC  1               
00E8DC  1  A5 D5            lda $D5                     ; $E8DC: A5 D5
00E8DE  1  10 03            bpl UpdatePrimaryArithmeticPair_SaveMask
00E8E0  1                                               ; $E8DE: 10 03
00E8E0  1               
00E8E0  1               ; ----------------------------------------------------------------------------
00E8E0  1               ; Negative high/source byte:
00E8E0  1               ;
00E8E0  1               ;   X is decremented from the caller's current value.
00E8E0  1               ;   A is one's-complemented.
00E8E0  1               ; ----------------------------------------------------------------------------
00E8E0  1               
00E8E0  1  CA               dex                         ; $E8E0: CA
00E8E1  1  49 FF            eor #$FF                    ; $E8E1: 49 FF
00E8E3  1               
00E8E3  1               UpdatePrimaryArithmeticPair_SaveMask: ; $E8E3
00E8E3  1  86 DA            stx $DA                     ; $E8E3: 86 DA
00E8E5  1               
00E8E5  1               ; ----------------------------------------------------------------------------
00E8E5  1               ; Shift A right by the current count in $DB.
00E8E5  1               ;
00E8E5  1               ; When $DB is zero, no shift is performed.
00E8E5  1               ; ----------------------------------------------------------------------------
00E8E5  1               
00E8E5  1  A6 DB            ldx $DB                     ; $E8E5: A6 DB
00E8E7  1  F0 04            beq UpdatePrimaryArithmeticPair_AddLow
00E8E9  1                                               ; $E8E7: F0 04
00E8E9  1               
00E8E9  1               UpdatePrimaryArithmeticPair_ShiftLow: ; $E8E9
00E8E9  1  4A               lsr                         ; $E8E9: 4A
00E8EA  1  CA               dex                         ; $E8EA: CA
00E8EB  1  D0 FC            bne UpdatePrimaryArithmeticPair_ShiftLow
00E8ED  1                                               ; $E8EB: D0 FC
00E8ED  1               
00E8ED  1               ; ----------------------------------------------------------------------------
00E8ED  1               ; Add the shifted value to $D4.
00E8ED  1               ;
00E8ED  1               ; Carry intentionally comes from the final LSR or from the preceding sign
00E8ED  1               ; setup when no shift occurred.
00E8ED  1               ; ----------------------------------------------------------------------------
00E8ED  1               
00E8ED  1               UpdatePrimaryArithmeticPair_AddLow: ; $E8ED
00E8ED  1  65 D4            adc $D4                     ; $E8ED: 65 D4
00E8EF  1  48               pha                         ; $E8EF: 48
00E8F0  1                                               ; Preserve the new low/result byte.
00E8F0  1               
00E8F0  1               ; ----------------------------------------------------------------------------
00E8F0  1               ; Build the high/source contribution:
00E8F0  1               ;
00E8F0  1               ;   A = ($DA XOR $FF XOR $D4)
00E8F0  1               ;
00E8F0  1               ; Then arithmetically shift it right by $DB.
00E8F0  1               ; ----------------------------------------------------------------------------
00E8F0  1               
00E8F0  1  A5 DA            lda $DA                     ; $E8F0: A5 DA
00E8F2  1  49 FF            eor #$FF                    ; $E8F2: 49 FF
00E8F4  1  45 D4            eor $D4                     ; $E8F4: 45 D4
00E8F6  1               
00E8F6  1  A6 DB            ldx $DB                     ; $E8F6: A6 DB
00E8F8  1  F0 06            beq UpdatePrimaryArithmeticPair_AddHigh
00E8FA  1                                               ; $E8F8: F0 06
00E8FA  1               
00E8FA  1               UpdatePrimaryArithmeticPair_ShiftHigh: ; $E8FA
00E8FA  1  C9 80            cmp #$80                    ; $E8FA: C9 80
00E8FC  1                                               ; Copy the sign bit into carry.
00E8FC  1               
00E8FC  1  6A               ror                         ; $E8FC: 6A
00E8FD  1                                               ; Arithmetic right shift.
00E8FD  1               
00E8FD  1  CA               dex                         ; $E8FD: CA
00E8FE  1  D0 FA            bne UpdatePrimaryArithmeticPair_ShiftHigh
00E900  1                                               ; $E8FE: D0 FA
00E900  1               
00E900  1               ; ----------------------------------------------------------------------------
00E900  1               ; Add the shifted high/source result to $D5.
00E900  1               ; ----------------------------------------------------------------------------
00E900  1               
00E900  1               UpdatePrimaryArithmeticPair_AddHigh: ; $E900
00E900  1  65 D5            adc $D5                     ; $E900: 65 D5
00E902  1  85 D5            sta $D5                     ; $E902: 85 D5
00E904  1               
00E904  1               ; ----------------------------------------------------------------------------
00E904  1               ; Restore and save the low/result byte.
00E904  1               ; ----------------------------------------------------------------------------
00E904  1               
00E904  1  68               pla                         ; $E904: 68
00E905  1  85 D4            sta $D4                     ; $E905: 85 D4
00E907  1               
00E907  1  60               rts                         ; $E907: 60
00E908  1               
00E908  1               ; ============================================================================
00E908  1               ; $E908-$E930
00E908  1               ; Apply the current per-round mask and shift state to result pair $D6/$D7.
00E908  1               ;
00E908  1               ; Working state:
00E908  1               ;   $D6/$D7 = secondary accumulator/result pair
00E908  1               ;   $DA     = sign/mask byte
00E908  1               ;   $DB     = shift count
00E908  1               ;
00E908  1               ; Exit:
00E908  1               ;   $D6/$D7 updated in place
00E908  1               ;
00E908  1               ; This routine is paired with UpdatePrimaryArithmeticPair and is called after
00E908  1               ; each common arithmetic round by multiple vector helpers.
00E908  1               ; ============================================================================
00E908  1               
00E908  1               ; ----------------------------------------------------------------------------
00E908  1               ; Contract:
00E908  1               ;   Description: Updates Secondary Arithmetic Pair.
00E908  1               ;   Entry: Registers: A, X; Memory: $da, $d7, $db, $d6
00E908  1               ;   Returns/products: Registers/clobbers: A, X
00E908  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E908  1               ;   Memory effects: $d7, $d6
00E908  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E908  1               ;          comparison, load, or store path and are not a stable API product.
00E908  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 3.
00E908  1               ; ----------------------------------------------------------------------------
00E908  1               UpdateSecondaryArithmeticPair:  ; $E908
00E908  1  A5 DA            lda $DA                     ; $E908: A5 DA
00E90A  1  49 FF            eor #$FF                    ; $E90A: 49 FF
00E90C  1  45 D7            eor $D7                     ; $E90C: 45 D7
00E90E  1               
00E90E  1               ; ----------------------------------------------------------------------------
00E90E  1               ; Arithmetically shift the sign-corrected high contribution by $DB.
00E90E  1               ; ----------------------------------------------------------------------------
00E90E  1               
00E90E  1  A6 DB            ldx $DB                     ; $E90E: A6 DB
00E910  1  F0 06            beq UpdateSecondaryArithmeticPair_AddLow
00E912  1                                               ; $E910: F0 06
00E912  1               
00E912  1               UpdateSecondaryArithmeticPair_ShiftLow: ; $E912
00E912  1  C9 80            cmp #$80                    ; $E912: C9 80
00E914  1  6A               ror                         ; $E914: 6A
00E915  1               
00E915  1  CA               dex                         ; $E915: CA
00E916  1  D0 FA            bne UpdateSecondaryArithmeticPair_ShiftLow
00E918  1                                               ; $E916: D0 FA
00E918  1               
00E918  1               ; ----------------------------------------------------------------------------
00E918  1               ; Add the shifted contribution to $D6.
00E918  1               ; ----------------------------------------------------------------------------
00E918  1               
00E918  1               UpdateSecondaryArithmeticPair_AddLow: ; $E918
00E918  1  65 D6            adc $D6                     ; $E918: 65 D6
00E91A  1  48               pha                         ; $E91A: 48
00E91B  1                                               ; Preserve the new low/result byte.
00E91B  1               
00E91B  1               ; ----------------------------------------------------------------------------
00E91B  1               ; Build and shift the contribution for $D7.
00E91B  1               ; ----------------------------------------------------------------------------
00E91B  1               
00E91B  1  A5 DA            lda $DA                     ; $E91B: A5 DA
00E91D  1  45 D6            eor $D6                     ; $E91D: 45 D6
00E91F  1               
00E91F  1  A6 DB            ldx $DB                     ; $E91F: A6 DB
00E921  1  F0 06            beq UpdateSecondaryArithmeticPair_AddHigh
00E923  1                                               ; $E921: F0 06
00E923  1               
00E923  1               UpdateSecondaryArithmeticPair_ShiftHigh: ; $E923
00E923  1  C9 80            cmp #$80                    ; $E923: C9 80
00E925  1  6A               ror                         ; $E925: 6A
00E926  1               
00E926  1  CA               dex                         ; $E926: CA
00E927  1  D0 FA            bne UpdateSecondaryArithmeticPair_ShiftHigh
00E929  1                                               ; $E927: D0 FA
00E929  1               
00E929  1               ; ----------------------------------------------------------------------------
00E929  1               ; Add the shifted contribution to $D7.
00E929  1               ; ----------------------------------------------------------------------------
00E929  1               
00E929  1               UpdateSecondaryArithmeticPair_AddHigh: ; $E929
00E929  1  65 D7            adc $D7                     ; $E929: 65 D7
00E92B  1  85 D7            sta $D7                     ; $E92B: 85 D7
00E92D  1               
00E92D  1               ; ----------------------------------------------------------------------------
00E92D  1               ; Restore and save the low/result byte.
00E92D  1               ; ----------------------------------------------------------------------------
00E92D  1               
00E92D  1  68               pla                         ; $E92D: 68
00E92E  1  85 D6            sta $D6                     ; $E92E: 85 D6
00E930  1               
00E930  1  60               rts                         ; $E930: 60
00E931  1               
00E931  1               ; ============================================================================
00E931  1               ; $E931-$E964
00E931  1               ; Alternate per-round update for source pair $D4/$D5.
00E931  1               ;
00E931  1               ; This helper differs from the $E8DA version in two ways:
00E931  1               ;
00E931  1               ;   1. It derives $DA from the opposite sign condition.
00E931  1               ;   2. Shift counts below four are increased by one.
00E931  1               ;
00E931  1               ; Working state:
00E931  1               ;   $D4/$D5 = signed or fixed-point accumulator
00E931  1               ;   $DA     = per-round sign/mask byte
00E931  1               ;   $DB     = shift count, incremented at the start of the round
00E931  1               ;
00E931  1               ; Exit:
00E931  1               ;   $D4/$D5 updated in place
00E931  1               ; ============================================================================
00E931  1               
00E931  1               ; ----------------------------------------------------------------------------
00E931  1               ; Contract:
00E931  1               ;   Description: Updates Primary Arithmetic Pair Alternate.
00E931  1               ;   Entry: Registers: A, X; Memory: $d5, $db, $d4, $da
00E931  1               ;   Returns/products: Registers/clobbers: A, X
00E931  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E931  1               ;   Memory effects: $da, $d5, $d4
00E931  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E931  1               ;          comparison, load, or store path and are not a stable API product.
00E931  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00E931  1               ; ----------------------------------------------------------------------------
00E931  1               UpdatePrimaryArithmeticPairAlternate: ; $E931
00E931  1  E6 DB            inc $DB                     ; $E931: E6 DB
00E933  1               
00E933  1  A5 D5            lda $D5                     ; $E933: A5 D5
00E935  1  30 03            bmi UpdatePrimaryArithmeticPairAlternate_SaveMask
00E937  1                                               ; $E935: 30 03
00E937  1               
00E937  1               ; ----------------------------------------------------------------------------
00E937  1               ; Nonnegative high/source byte:
00E937  1               ;
00E937  1               ;   A is one's-complemented.
00E937  1               ;   X is decremented.
00E937  1               ; ----------------------------------------------------------------------------
00E937  1               
00E937  1  49 FF            eor #$FF                    ; $E937: 49 FF
00E939  1  CA               dex                         ; $E939: CA
00E93A  1               
00E93A  1               UpdatePrimaryArithmeticPairAlternate_SaveMask: ; $E93A
00E93A  1  86 DA            stx $DA                     ; $E93A: 86 DA
00E93C  1               
00E93C  1               ; ----------------------------------------------------------------------------
00E93C  1               ; Load the shift count.
00E93C  1               ;
00E93C  1               ; Counts below four are increased by one.
00E93C  1               ; ----------------------------------------------------------------------------
00E93C  1               
00E93C  1  A6 DB            ldx $DB                     ; $E93C: A6 DB
00E93E  1  E0 04            cpx #$04                    ; $E93E: E0 04
00E940  1  B0 01            bcs UpdatePrimaryArithmeticPairAlternate_ShiftLow
00E942  1                                               ; $E940: B0 01
00E942  1               
00E942  1  E8               inx                         ; $E942: E8
00E943  1               
00E943  1               ; ----------------------------------------------------------------------------
00E943  1               ; Arithmetically shift A right by the adjusted count.
00E943  1               ; ----------------------------------------------------------------------------
00E943  1               
00E943  1               UpdatePrimaryArithmeticPairAlternate_ShiftLow: ; $E943
00E943  1  C9 80            cmp #$80                    ; $E943: C9 80
00E945  1  6A               ror                         ; $E945: 6A
00E946  1               
00E946  1  CA               dex                         ; $E946: CA
00E947  1  D0 FA            bne UpdatePrimaryArithmeticPairAlternate_ShiftLow
00E949  1                                               ; $E947: D0 FA
00E949  1               
00E949  1               ; ----------------------------------------------------------------------------
00E949  1               ; Add the shifted result to $D4.
00E949  1               ; ----------------------------------------------------------------------------
00E949  1               
00E949  1  65 D4            adc $D4                     ; $E949: 65 D4
00E94B  1  48               pha                         ; $E94B: 48
00E94C  1               
00E94C  1               ; ----------------------------------------------------------------------------
00E94C  1               ; Build the contribution for $D5.
00E94C  1               ; ----------------------------------------------------------------------------
00E94C  1               
00E94C  1  A5 DA            lda $DA                     ; $E94C: A5 DA
00E94E  1  45 D4            eor $D4                     ; $E94E: 45 D4
00E950  1               
00E950  1               ; ----------------------------------------------------------------------------
00E950  1               ; Apply the same adjusted shift-count rule.
00E950  1               ; ----------------------------------------------------------------------------
00E950  1               
00E950  1  A6 DB            ldx $DB                     ; $E950: A6 DB
00E952  1  E0 04            cpx #$04                    ; $E952: E0 04
00E954  1  B0 01            bcs UpdatePrimaryArithmeticPairAlternate_ShiftHigh
00E956  1                                               ; $E954: B0 01
00E956  1               
00E956  1  E8               inx                         ; $E956: E8
00E957  1               
00E957  1               UpdatePrimaryArithmeticPairAlternate_ShiftHigh: ; $E957
00E957  1  C9 80            cmp #$80                    ; $E957: C9 80
00E959  1  6A               ror                         ; $E959: 6A
00E95A  1               
00E95A  1  CA               dex                         ; $E95A: CA
00E95B  1  D0 FA            bne UpdatePrimaryArithmeticPairAlternate_ShiftHigh
00E95D  1                                               ; $E95B: D0 FA
00E95D  1               
00E95D  1               ; ----------------------------------------------------------------------------
00E95D  1               ; Add the shifted contribution to $D5.
00E95D  1               ; ----------------------------------------------------------------------------
00E95D  1               
00E95D  1  65 D5            adc $D5                     ; $E95D: 65 D5
00E95F  1  85 D5            sta $D5                     ; $E95F: 85 D5
00E961  1               
00E961  1               ; ----------------------------------------------------------------------------
00E961  1               ; Restore and save the updated low/result byte.
00E961  1               ; ----------------------------------------------------------------------------
00E961  1               
00E961  1  68               pla                         ; $E961: 68
00E962  1  85 D4            sta $D4                     ; $E962: 85 D4
00E964  1               
00E964  1  60               rts                         ; $E964: 60
00E965  1               
00E965  1               ; ============================================================================
00E965  1               ; $E965-$E96B
00E965  1               ; Calculate a scaled ratio by chaining the multiplication and division helpers.
00E965  1               ;
00E965  1               ; Entry and exit registers depend on the callers:
00E965  1               ;
00E965  1               ;   CalculateScaledProduct = $E7DB
00E965  1               ;   DivideUnsignedByte     = $E7F5
00E965  1               ; ============================================================================
00E965  1               
00E965  1               ; ----------------------------------------------------------------------------
00E965  1               ; Contract:
00E965  1               ;   Description: Calculates Scaled Ratio.
00E965  1               ;   Entry: No register input inferred
00E965  1               ;   Returns/products: No direct product inferred
00E965  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E965  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00E965  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E965  1               ;          comparison, load, or store path and are not a stable API product.
00E965  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00E965  1               ; ----------------------------------------------------------------------------
00E965  1               CalculateScaledRatio:           ; $E965
00E965  1  20 DB E7         jsr CalculateScaledProduct  ; $E965: 20 DB E7
00E968  1  20 F5 E7         jsr DivideUnsignedByte      ; $E968: 20 F5 E7
00E96B  1  60               rts                         ; $E96B: 60
00E96C  1               
00E96C  1               ; ============================================================================
00E96C  1               ; $E96C-$E977
00E96C  1               ; Disable PPU rendering and read PPUSTATUS.
00E96C  1               ;
00E96C  1               ; Exit:
00E96C  1               ;   Rendering is disabled.
00E96C  1               ;   A contains the value read from PPUSTATUS.
00E96C  1               ; ============================================================================
00E96C  1               
00E96C  1               ; ----------------------------------------------------------------------------
00E96C  1               ; Contract:
00E96C  1               ;   Description: Implements Disable Ppu Rendering.
00E96C  1               ;   Entry: Registers: A; Memory: $2002
00E96C  1               ;   Returns/products: Registers/clobbers: A
00E96C  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E96C  1               ;   Memory effects: $2000, $2001
00E96C  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E96C  1               ;          comparison, load, or store path and are not a stable API product.
00E96C  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 4.
00E96C  1               ; ----------------------------------------------------------------------------
00E96C  1               DisablePpuRendering:            ; $E96C
00E96C  1  A9 00            lda #$00                    ; $E96C: A9 00
00E96E  1               
00E96E  1  8D 00 20         sta $2000                   ; $E96E: 8D 00 20
00E971  1                                               ; Disable NMI and reset PPUCTRL state.
00E971  1               
00E971  1  8D 01 20         sta $2001                   ; $E971: 8D 01 20
00E974  1                                               ; Disable background and sprite rendering.
00E974  1               
00E974  1  AD 02 20         lda $2002                   ; $E974: AD 02 20
00E977  1                                               ; Read PPUSTATUS and reset the address latch.
00E977  1               
00E977  1  60               rts                         ; $E977: 60
00E978  1               
00E978  1               ; ============================================================================
00E978  1               ; $E978-$E982
00E978  1               ; Reset the PPU address latch, enable NMI, and jump to the frame-wait helper.
00E978  1               ; ============================================================================
00E978  1               
00E978  1               ; ----------------------------------------------------------------------------
00E978  1               ; Contract:
00E978  1               ;   Description: Implements Enable Nmi And Wait For Frame.
00E978  1               ;   Entry: Registers: A; Memory: $2002
00E978  1               ;   Returns/products: Registers/clobbers: A
00E978  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E978  1               ;   Memory effects: $2000
00E978  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E978  1               ;          comparison, load, or store path and are not a stable API product.
00E978  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 2.
00E978  1               ; ----------------------------------------------------------------------------
00E978  1               EnableNmiAndWaitForFrame:       ; $E978
00E978  1  AD 02 20         lda $2002                   ; $E978: AD 02 20
00E97B  1                                               ; Reset the PPU address latch.
00E97B  1               
00E97B  1  A9 80            lda #$80                    ; $E97B: A9 80
00E97D  1  8D 00 20         sta $2000                   ; $E97D: 8D 00 20
00E980  1                                               ; Enable NMI.
00E980  1               
00E980  1  4C 48 EB         jmp SelectObjectEventBank1                   ; $E980: 4C 48 EB
00E983  1               
00E983  1               ; ============================================================================
00E983  1               ; $E983-$E999
00E983  1               ; Fill $1000 bytes of PPU memory with tile/value $26.
00E983  1               ;
00E983  1               ; The helper at $E9DB consumes the two inline bytes following its JSR:
00E983  1               ;
00E983  1               ;   $00,$20
00E983  1               ;
00E983  1               ; These bytes appear to specify PPU address $2000 in little-endian order.
00E983  1               ; Execution resumes at the PLA instruction at $E98B.
00E983  1               ;
00E983  1               ; Operation:
00E983  1               ;   1. Preserve fill value $26 on the stack.
00E983  1               ;   2. Set the PPU destination address to $2000.
00E983  1               ;   3. Restore fill value $26.
00E983  1               ;   4. Write $26 to PPUDATA $1000 times.
00E983  1               ;
00E983  1               ; Total writes:
00E983  1               ;   $10 outer iterations * $100 inner iterations = $1000 bytes.
00E983  1               ; ============================================================================
00E983  1               
00E983  1               ; ----------------------------------------------------------------------------
00E983  1               ; Contract:
00E983  1               ;   Description: Implements Fill Ppu Memory With 2 6.
00E983  1               ;   Entry: Registers: A, X, Y
00E983  1               ;   Returns/products: Registers/clobbers: A, X, Y
00E983  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E983  1               ;   Memory effects: $2007
00E983  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E983  1               ;          comparison, load, or store path and are not a stable API product.
00E983  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00E983  1               ; ----------------------------------------------------------------------------
00E983  1               FillPpuMemoryWith26:            ; $E983
00E983  1  A9 26            lda #$26                    ; $E983: A9 26
00E985  1                                               ; Tile or fill value.
00E985  1               
00E985  1               ; ----------------------------------------------------------------------------
00E985  1               ; Contract:
00E985  1               ;   Description: Internal PPU-fill entry after the fill value has been pushed.
00E985  1               ;   Entry: Stack top = fill value.
00E985  1               ;   Returns/products: PPU region filled; A/X/Y clobbered.
00E985  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E985  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00E985  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E985  1               ;          comparison, load, or store path and are not a stable API product.
00E985  1               ;   Validation: Internal-entry contract; call sites: internal entry.
00E985  1               ; ----------------------------------------------------------------------------
00E985  1               FillPpuMemoryAfterValueSaved:
00E985  1  48               pha                         ; $E985: 48
00E986  1                                               ; Preserve the fill value while the inline
00E986  1                                               ; PPU-address helper runs.
00E986  1               
00E986  1               ; ----------------------------------------------------------------------------
00E986  1               ; Set the PPU destination address using the inline address record.
00E986  1               ;
00E986  1               ; The JSR return-address logic in $E9DB advances execution past the two inline
00E986  1               ; bytes, so execution resumes at $E98B.
00E986  1               ; ----------------------------------------------------------------------------
00E986  1               
00E986  1  20 DB E9         jsr SetPpuAddressFromInlineRecord                   ; $E986: 20 DB E9
00E989  1               
00E989  1  00 20            .byte $00,$20               ; $E989-$E98A
00E98B  1                                               ; Inline PPU address: $2000.
00E98B  1               
00E98B  1               ; ----------------------------------------------------------------------------
00E98B  1               ; Restore the fill value.
00E98B  1               ; ----------------------------------------------------------------------------
00E98B  1               
00E98B  1  68               pla                         ; $E98B: 68
00E98C  1                                               ; A = $26.
00E98C  1               
00E98C  1               ; ----------------------------------------------------------------------------
00E98C  1               ; Initialize the outer and inner loop counters.
00E98C  1               ;
00E98C  1               ; X = $10 outer blocks.
00E98C  1               ; Y = $00, which produces 256 iterations because DEY wraps to $FF.
00E98C  1               ; ----------------------------------------------------------------------------
00E98C  1               
00E98C  1  A2 10            ldx #$10                    ; $E98C: A2 10
00E98E  1  A0 00            ldy #$00                    ; $E98E: A0 00
00E990  1               
00E990  1               ; ----------------------------------------------------------------------------
00E990  1               ; Write one byte to PPUDATA.
00E990  1               ;
00E990  1               ; The PPU automatically increments its internal VRAM address after the write.
00E990  1               ; ----------------------------------------------------------------------------
00E990  1               
00E990  1               FillPpuMemoryWith26_Loop:       ; $E990
00E990  1  8D 07 20         sta $2007                   ; $E990: 8D 07 20
00E993  1               
00E993  1               ; ----------------------------------------------------------------------------
00E993  1               ; Process 256 bytes in the current outer block.
00E993  1               ;
00E993  1               ; Starting from Y=$00:
00E993  1               ;
00E993  1               ;   first DEY -> $FF
00E993  1               ;   ...
00E993  1               ;   final DEY -> $00
00E993  1               ; ----------------------------------------------------------------------------
00E993  1               
00E993  1  88               dey                         ; $E993: 88
00E994  1  D0 FA            bne FillPpuMemoryWith26_Loop
00E996  1                                               ; $E994: D0 FA
00E996  1               
00E996  1               ; ----------------------------------------------------------------------------
00E996  1               ; Process sixteen 256-byte blocks.
00E996  1               ;
00E996  1               ; The branch returns directly to the PPUDATA write at $E990. Y is already zero
00E996  1               ; after each completed inner iteration, so the next block again runs 256 times.
00E996  1               ; ----------------------------------------------------------------------------
00E996  1               
00E996  1  CA               dex                         ; $E996: CA
00E997  1  D0 F7            bne FillPpuMemoryWith26_Loop
00E999  1                                               ; $E997: D0 F7
00E999  1               
00E999  1  60               rts                         ; $E999: 60
00E99A  1               
00E99A  1               ; ============================================================================
00E99A  1               ; $E99A-$E9B3
00E99A  1               ; Decode inline parameters following a caller's JSR instruction.
00E99A  1               ;
00E99A  1               ; This routine manipulates two return addresses:
00E99A  1               ;
00E99A  1               ;   1. The return address from JSR $E99A.
00E99A  1               ;   2. The return address belonging to the helper that called $E99A.
00E99A  1               ;
00E99A  1               ; It reads two inline parameter bytes through ReadInlineWord, advances the
00E99A  1               ; outer return address past the inline record, and jumps to that continuation.
00E99A  1               ;
00E99A  1               ; ReadInlineWord restores the immediate caller's return address to the stack,
00E99A  1               ; allowing that helper to return normally after processing the parameters.
00E99A  1               ; ============================================================================
00E99A  1               
00E99A  1               ; ----------------------------------------------------------------------------
00E99A  1               ; Contract:
00E99A  1               ;   Description: Implements Decode Inline Parameters.
00E99A  1               ;   Entry: Registers: A, Y; Memory: $00
00E99A  1               ;   Returns/products: Registers/clobbers: A, X, Y
00E99A  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E99A  1               ;   Memory effects: $00, $01
00E99A  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E99A  1               ;          comparison, load, or store path and are not a stable API product.
00E99A  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 10.
00E99A  1               ; ----------------------------------------------------------------------------
00E99A  1               DecodeInlineParameters:         ; $E99A
00E99A  1  68               pla                         ; $E99A: 68
00E99B  1  AA               tax                         ; $E99B: AA
00E99C  1                                               ; X = low byte of the immediate return address.
00E99C  1               
00E99C  1  68               pla                         ; $E99C: 68
00E99D  1  A8               tay                         ; $E99D: A8
00E99E  1                                               ; Y = high byte of the immediate return address.
00E99E  1               
00E99E  1               ; ----------------------------------------------------------------------------
00E99E  1               ; Remove the outer caller's return address and store it as a pointer.
00E99E  1               ; ----------------------------------------------------------------------------
00E99E  1               
00E99E  1  68               pla                         ; $E99E: 68
00E99F  1  85 00            sta $00                     ; $E99F: 85 00
00E9A1  1               
00E9A1  1  68               pla                         ; $E9A1: 68
00E9A2  1  85 01            sta $01                     ; $E9A2: 85 01
00E9A4  1               
00E9A4  1               ; ----------------------------------------------------------------------------
00E9A4  1               ; Restore the immediate return address and read two bytes following the outer
00E9A4  1               ; caller's JSR.
00E9A4  1               ;
00E9A4  1               ; Exit from ReadInlineWord:
00E9A4  1               ;   X = first inline byte
00E9A4  1               ;   A = second inline byte
00E9A4  1               ;   Y = $03
00E9A4  1               ; ----------------------------------------------------------------------------
00E9A4  1               
00E9A4  1  20 B4 E9         jsr ReadInlineWord          ; $E9A4: 20 B4 E9
00E9A7  1               
00E9A7  1               ; ----------------------------------------------------------------------------
00E9A7  1               ; Advance the outer return pointer by three:
00E9A7  1               ;
00E9A7  1               ;   one byte for the JSR return-address convention
00E9A7  1               ;   two bytes for the inline parameter record
00E9A7  1               ; ----------------------------------------------------------------------------
00E9A7  1               
00E9A7  1  18               clc                         ; $E9A7: 18
00E9A8  1               
00E9A8  1  98               tya                         ; $E9A8: 98
00E9A9  1  65 00            adc $00                     ; $E9A9: 65 00
00E9AB  1  85 00            sta $00                     ; $E9AB: 85 00
00E9AD  1               
00E9AD  1  90 02            bcc DecodeInlineParameters_Jump
00E9AF  1                                               ; $E9AD: 90 02
00E9AF  1               
00E9AF  1  E6 01            inc $01                     ; $E9AF: E6 01
00E9B1  1               
00E9B1  1               ; ----------------------------------------------------------------------------
00E9B1  1               ; Continue execution immediately after the inline record.
00E9B1  1               ; ----------------------------------------------------------------------------
00E9B1  1               
00E9B1  1               DecodeInlineParameters_Jump:    ; $E9B1
00E9B1  1  6C 00 00         jmp ($0000)                 ; $E9B1: 6C 00 00
00E9B4  1               
00E9B4  1               ; ============================================================================
00E9B4  1               ; $E9B4-$E9C1
00E9B4  1               ; Restore an immediate caller return address and read a two-byte inline word.
00E9B4  1               ;
00E9B4  1               ; Entry:
00E9B4  1               ;   X/Y = low/high bytes of the immediate caller's return address
00E9B4  1               ;   $00/$01 = pointer to the outer caller's return address
00E9B4  1               ;
00E9B4  1               ; Exit:
00E9B4  1               ;   X = first byte following the outer caller's JSR
00E9B4  1               ;   A = second byte following the outer caller's JSR
00E9B4  1               ;   Y = $03
00E9B4  1               ;
00E9B4  1               ; The initial TYA/PHA and TXA/PHA restore the immediate return address to the
00E9B4  1               ; stack in the order required by RTS.
00E9B4  1               ; ============================================================================
00E9B4  1               
00E9B4  1               ; ----------------------------------------------------------------------------
00E9B4  1               ; Contract:
00E9B4  1               ;   Description: Implements Read Inline Word.
00E9B4  1               ;   Entry: Registers: A, X, Y; Memory: ($00)
00E9B4  1               ;   Returns/products: Registers/clobbers: A, X, Y
00E9B4  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E9B4  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00E9B4  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E9B4  1               ;          comparison, load, or store path and are not a stable API product.
00E9B4  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00E9B4  1               ; ----------------------------------------------------------------------------
00E9B4  1               ReadInlineWord:                 ; $E9B4
00E9B4  1  98               tya                         ; $E9B4: 98
00E9B5  1  48               pha                         ; $E9B5: 48
00E9B6  1                                               ; Restore return-address high byte.
00E9B6  1               
00E9B6  1  8A               txa                         ; $E9B6: 8A
00E9B7  1  48               pha                         ; $E9B7: 48
00E9B8  1                                               ; Restore return-address low byte.
00E9B8  1               
00E9B8  1  A0 01            ldy #$01                    ; $E9B8: A0 01
00E9BA  1               
00E9BA  1  B1 00            lda ($00),y                 ; $E9BA: B1 00
00E9BC  1  AA               tax                         ; $E9BC: AA
00E9BD  1                                               ; X = first inline parameter.
00E9BD  1               
00E9BD  1  C8               iny                         ; $E9BD: C8
00E9BE  1               
00E9BE  1  B1 00            lda ($00),y                 ; $E9BE: B1 00
00E9C0  1                                               ; A = second inline parameter.
00E9C0  1               
00E9C0  1  C8               iny                         ; $E9C0: C8
00E9C1  1                                               ; Y = $03.
00E9C1  1               
00E9C1  1  60               rts                         ; $E9C1: 60
00E9C2  1               
00E9C2  1               ; ============================================================================
00E9C2  1               ; $E9C2-$E9D1
00E9C2  1               ; Copy a counted inline byte sequence into zero page.
00E9C2  1               ;
00E9C2  1               ; Inline record:
00E9C2  1               ;   byte 0 = destination zero-page address
00E9C2  1               ;   byte 1 = byte count
00E9C2  1               ;   remaining bytes = data to copy
00E9C2  1               ;
00E9C2  1               ; DecodeInlineParameters returns:
00E9C2  1               ;   X = destination zero-page address
00E9C2  1               ;   A = byte count
00E9C2  1               ;   Y = index of the first data byte
00E9C2  1               ;
00E9C2  1               ; Exit:
00E9C2  1               ;   X points immediately after the destination range.
00E9C2  1               ; ============================================================================
00E9C2  1               
00E9C2  1               CopyInlineBytesToZeroPage:      ; $E9C2
00E9C2  1  20 9A E9         jsr DecodeInlineParameters  ; $E9C2: 20 9A E9
00E9C5  1               
00E9C5  1  85 04            sta $04                     ; $E9C5: 85 04
00E9C7  1                                               ; Save byte count.
00E9C7  1               
00E9C7  1               CopyInlineBytesToZeroPage_Loop: ; $E9C7
00E9C7  1  B1 00            lda ($00),y                 ; $E9C7: B1 00
00E9C9  1  95 00            sta $00,x                   ; $E9C9: 95 00
00E9CB  1               
00E9CB  1  C8               iny                         ; $E9CB: C8
00E9CC  1  E8               inx                         ; $E9CC: E8
00E9CD  1               
00E9CD  1  C6 04            dec $04                     ; $E9CD: C6 04
00E9CF  1  D0 F6            bne CopyInlineBytesToZeroPage_Loop
00E9D1  1                                               ; $E9CF: D0 F6
00E9D1  1               
00E9D1  1  60               rts                         ; $E9D1: 60
00E9D2  1               
00E9D2  1               ; ============================================================================
00E9D2  1               ; $E9D2-$E9DA
00E9D2  1               ; Set PPUCTRL according to the incoming carry flag.
00E9D2  1               ;
00E9D2  1               ; Entry:
00E9D2  1               ;   C = clear -> write $00 to PPUCTRL
00E9D2  1               ;   C = set   -> write $04 to PPUCTRL
00E9D2  1               ;
00E9D2  1               ; LDA #$00 preserves carry. Three ROL instructions move the incoming carry
00E9D2  1               ; into bit two of A.
00E9D2  1               ; ============================================================================
00E9D2  1               
00E9D2  1               WritePpuControlFromCarry:       ; $E9D2
00E9D2  1  A9 00            lda #$00                    ; $E9D2: A9 00
00E9D4  1               
00E9D4  1  2A               rol                         ; $E9D4: 2A
00E9D5  1  2A               rol                         ; $E9D5: 2A
00E9D6  1  2A               rol                         ; $E9D6: 2A
00E9D7  1               
00E9D7  1  8D 00 20         sta $2000                   ; $E9D7: 8D 00 20
00E9DA  1               
00E9DA  1  60               rts                         ; $E9DA: 60
00E9DB  1               
00E9DB  1               ; ============================================================================
00E9DB  1               ; $E9DB-$E9FB
00E9DB  1               ; Decode an inline PPU address, update the address shadow in $23/$24, and write
00E9DB  1               ; the resulting address to PPUADDR.
00E9DB  1               ;
00E9DB  1               ; Inline record:
00E9DB  1               ;   byte 0 = low address byte or signed relative offset
00E9DB  1               ;   byte 1 = high address byte
00E9DB  1               ;
00E9DB  1               ; Modes:
00E9DB  1               ;
00E9DB  1               ;   High byte nonzero:
00E9DB  1               ;       Use the decoded X:A pair as an absolute PPU address.
00E9DB  1               ;
00E9DB  1               ;   High byte zero:
00E9DB  1               ;       Treat the decoded low byte in X as a signed offset and add it to the
00E9DB  1               ;       current shadow PPU address in $23/$24.
00E9DB  1               ;
00E9DB  1               ; Exit:
00E9DB  1               ;   $23/$24 = selected PPU address
00E9DB  1               ;   PPUADDR  = selected PPU address
00E9DB  1               ;   X restored from $05
00E9DB  1               ; ============================================================================
00E9DB  1               
00E9DB  1               ; ----------------------------------------------------------------------------
00E9DB  1               ; Contract:
00E9DB  1               ;   Description: Implements Set Ppu Address From Inline Record.
00E9DB  1               ;   Entry: Registers: A, X, Y; Memory: $23, $24, mathtemp05
00E9DB  1               ;   Returns/products: Registers/clobbers: A, X, Y
00E9DB  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00E9DB  1               ;   Memory effects: $05, $24, ppuaddr, $23
00E9DB  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00E9DB  1               ;          comparison, load, or store path and are not a stable API product.
00E9DB  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00E9DB  1               ; ----------------------------------------------------------------------------
00E9DB  1               SetPpuAddressFromInlineRecord:  ; $E9DB
00E9DB  1  20 9A E9         jsr DecodeInlineParameters  ; $E9DB: 20 9A E9
00E9DE  1                                               ; X = first inline byte
00E9DE  1                                               ; A = second inline byte
00E9DE  1               
00E9DE  1               ; ----------------------------------------------------------------------------
00E9DE  1               ; A nonzero high byte selects the absolute-address path.
00E9DE  1               ;
00E9DE  1               ; The decoded values remain:
00E9DE  1               ;   A = address high byte
00E9DE  1               ;   X = address low byte
00E9DE  1               ; ----------------------------------------------------------------------------
00E9DE  1               
00E9DE  1  D0 0F            bne SetPpuAddress_Write     ; $E9DE: D0 0F
00E9E0  1               
00E9E0  1               ; ----------------------------------------------------------------------------
00E9E0  1               ; A is zero, so interpret X as a signed relative offset.
00E9E0  1               ;
00E9E0  1               ; Preserve the decoded low byte in $05 because X is used during the signed
00E9E0  1               ; addition.
00E9E0  1               ; ----------------------------------------------------------------------------
00E9E0  1               SetRelativePpuAddressFromInlineRecord:
00E9E0  1  86 05            stx $05                     ; $E9E0: 86 05
00E9E2  1               
00E9E2  1  A0 00            ldy #$00                    ; $E9E2: A0 00
00E9E4  1                                               ; Default sign-extension byte.
00E9E4  1               
00E9E4  1  AA               tax                         ; $E9E4: AA
00E9E5  1                                               ; A is zero, so X becomes zero.
00E9E5  1               
00E9E5  1               ; ----------------------------------------------------------------------------
00E9E5  1               ; Test the sign of the decoded relative offset.
00E9E5  1               ;
00E9E5  1               ; DecodeInlineParameters left the low parameter in X before TAX. The flags used
00E9E5  1               ; by BPL are preserved from TAX, which loaded zero here. Preserve the original
00E9E5  1               ; instruction sequence byte-for-byte because callers may depend on the helper's
00E9E5  1               ; exact inline-data convention.
00E9E5  1               ; ----------------------------------------------------------------------------
00E9E5  1               
00E9E5  1  10 01            bpl SetPpuAddress_AddOffset ; $E9E5: 10 01
00E9E7  1               
00E9E7  1  88               dey                         ; $E9E7: 88
00E9E8  1                                               ; Sign extension $FF for a negative offset.
00E9E8  1               
00E9E8  1               ; ----------------------------------------------------------------------------
00E9E8  1               ; Add the signed offset to the current PPU address shadow.
00E9E8  1               ; ----------------------------------------------------------------------------
00E9E8  1               
00E9E8  1               SetPpuAddress_AddOffset:        ; $E9E8
00E9E8  1  18               clc                         ; $E9E8: 18
00E9E9  1               
00E9E9  1  65 23            adc $23                     ; $E9E9: 65 23
00E9EB  1  AA               tax                         ; $E9EB: AA
00E9EC  1                                               ; X = resulting low address byte.
00E9EC  1               
00E9EC  1  98               tya                         ; $E9EC: 98
00E9ED  1  65 24            adc $24                     ; $E9ED: 65 24
00E9EF  1                                               ; A = resulting high address byte.
00E9EF  1               
00E9EF  1               ; ----------------------------------------------------------------------------
00E9EF  1               ; Store and write the high address byte first.
00E9EF  1               ; ----------------------------------------------------------------------------
00E9EF  1               
00E9EF  1               SetPpuAddress_Write:            ; $E9EF
00E9EF  1  85 24            sta $24                     ; $E9EF: 85 24
00E9F1  1  8D 06 20         sta PPUADDR                 ; $E9F1: 8D 06 20
00E9F4  1               
00E9F4  1               ; ----------------------------------------------------------------------------
00E9F4  1               ; Store and write the low address byte.
00E9F4  1               ; ----------------------------------------------------------------------------
00E9F4  1               
00E9F4  1  86 23            stx $23                     ; $E9F4: 86 23
00E9F6  1  8E 06 20         stx PPUADDR                 ; $E9F6: 8E 06 20
00E9F9  1               
00E9F9  1               ; ----------------------------------------------------------------------------
00E9F9  1               ; Restore X from the scratch value at $05.
00E9F9  1               ; ----------------------------------------------------------------------------
00E9F9  1               
00E9F9  1  A6 05            ldx MathTemp05              ; $E9F9: A6 05
00E9FB  1               
00E9FB  1  60               rts                         ; $E9FB: 60
00E9FC  1               
00E9FC  1               ; ============================================================================
00E9FC  1               ; $E9FC-$EA01
00E9FC  1               ; Write the pending PPU data byte from $25 to PPUDATA.
00E9FC  1               ;
00E9FC  1               ; Entry:
00E9FC  1               ;   $25 = byte to write
00E9FC  1               ;
00E9FC  1               ; Exit:
00E9FC  1               ;   A = value written
00E9FC  1               ; ============================================================================
00E9FC  1               
00E9FC  1               WritePendingPpuByte:            ; $E9FC
00E9FC  1  A5 25            lda $25                     ; $E9FC: A5 25
00E9FE  1  8D 07 20         sta PPUDATA                 ; $E9FE: 8D 07 20
00EA01  1  60               rts                         ; $EA01: 60
00EA02  1               
00EA02  1               ; ============================================================================
00EA02  1               ; $EA02-$EA16
00EA02  1               ; Set a PPU address from inline data, then write a counted inline byte sequence
00EA02  1               ; to PPUDATA.
00EA02  1               ;
00EA02  1               ; Inline record structure:
00EA02  1               ;
00EA02  1               ;   bytes 0-1:
00EA02  1               ;       PPU address record consumed by SetPpuAddressFromInlineRecord
00EA02  1               ;
00EA02  1               ;   byte 2:
00EA02  1               ;       transfer count returned in X by DecodeInlineParameters
00EA02  1               ;
00EA02  1               ;   byte 3 onward:
00EA02  1               ;       data bytes written to PPUDATA
00EA02  1               ;
00EA02  1               ; Entry:
00EA02  1               ;   X may contain caller state that must be restored before return.
00EA02  1               ;
00EA02  1               ; Exit:
00EA02  1               ;   X restored from $05
00EA02  1               ;   Y points back to the final byte consumed from the inline record
00EA02  1               ; ============================================================================
00EA02  1               
00EA02  1               WriteInlinePpuBlock:            ; $EA02
00EA02  1  20 E0 E9         jsr SetRelativePpuAddressFromInlineRecord
00EA05  1                                               ; $EA02: 20 E0 E9
00EA05  1               
00EA05  1               ; ----------------------------------------------------------------------------
00EA05  1               ; Preserve X while the inline record is decoded.
00EA05  1               ; ----------------------------------------------------------------------------
00EA05  1               
00EA05  1               ; ----------------------------------------------------------------------------
00EA05  1               ; Contract:
00EA05  1               ;   Description: Internal PPU block writer after PPUADDR has already been set.
00EA05  1               ;   Entry: X = caller state; inline transfer record follows caller.
00EA05  1               ;   Returns/products: PPUDATA written; X restored from scratch state.
00EA05  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00EA05  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00EA05  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00EA05  1               ;          comparison, load, or store path and are not a stable API product.
00EA05  1               ;   Validation: Internal-entry contract; call sites: internal entry.
00EA05  1               ; ----------------------------------------------------------------------------
00EA05  1               WriteInlinePpuBlockAfterAddress:
00EA05  1  86 05            stx MathTemp05              ; $EA05: 86 05
00EA07  1               
00EA07  1               ; ----------------------------------------------------------------------------
00EA07  1               ; Decode the following inline parameter record.
00EA07  1               ;
00EA07  1               ; DecodeInlineParameters returns:
00EA07  1               ;   X = transfer count
00EA07  1               ;   A = first data byte
00EA07  1               ;   Y = index into the remaining inline data
00EA07  1               ; ----------------------------------------------------------------------------
00EA07  1               
00EA07  1  20 9A E9         jsr DecodeInlineParameters  ; $EA07: 20 9A E9
00EA0A  1               
00EA0A  1               ; ----------------------------------------------------------------------------
00EA0A  1               ; Write the first data byte returned directly in A.
00EA0A  1               ; ----------------------------------------------------------------------------
00EA0A  1               
00EA0A  1               WriteInlinePpuBlock_Loop:       ; $EA0A
00EA0A  1  8D 07 20         sta PPUDATA                 ; $EA0A: 8D 07 20
00EA0D  1               
00EA0D  1               ; ----------------------------------------------------------------------------
00EA0D  1               ; Load the next inline byte, advance the source index, and count down the
00EA0D  1               ; number of bytes remaining.
00EA0D  1               ;
00EA0D  1               ; On the final iteration, the loaded byte is not written because X reaches
00EA0D  1               ; zero immediately after the load. DEY then restores Y to the last byte that
00EA0D  1               ; was actually consumed.
00EA0D  1               ; ----------------------------------------------------------------------------
00EA0D  1               
00EA0D  1  B1 00            lda ($00),y                 ; $EA0D: B1 00
00EA0F  1  C8               iny                         ; $EA0F: C8
00EA10  1               
00EA10  1  CA               dex                         ; $EA10: CA
00EA11  1  D0 F7            bne WriteInlinePpuBlock_Loop
00EA13  1                                               ; $EA11: D0 F7
00EA13  1               
00EA13  1               ; ----------------------------------------------------------------------------
00EA13  1               ; Restore Y and X to the state expected by the inline dispatcher.
00EA13  1               ; ----------------------------------------------------------------------------
00EA13  1               
00EA13  1  88               dey                         ; $EA13: 88
00EA14  1               
00EA14  1  A6 05            ldx MathTemp05              ; $EA14: A6 05
00EA16  1               
00EA16  1  60               rts                         ; $EA16: 60
00EA17  1               
00EA17  1               ; ============================================================================
00EA17  1               ; $EA17-$EA3D
00EA17  1               ; Copy a counted inline record into the display buffer at $0300,X.
00EA17  1               ;
00EA17  1               ; The routine first calls $EA3E to reserve or initialize a display-buffer
00EA17  1               ; record. It then removes its caller's return address from the stack and uses
00EA17  1               ; that address as a pointer to inline data.
00EA17  1               ;
00EA17  1               ; Inline record:
00EA17  1               ;   byte 0 = number of data bytes
00EA17  1               ;   byte 1...N = bytes copied into $0300,X
00EA17  1               ;
00EA17  1               ; After copying the record, the routine rebuilds the return address so RTS
00EA17  1               ; resumes execution immediately after the inline data.
00EA17  1               ;
00EA17  1               ; Entry:
00EA17  1               ;   A, X, Y and carry contain parameters consumed by $EA3E.
00EA17  1               ;
00EA17  1               ; Exit:
00EA17  1               ;   X points immediately after the copied display-buffer bytes.
00EA17  1               ; ============================================================================
00EA17  1               PPUWriteString:
00EA17  1               ; ----------------------------------------------------------------------------
00EA17  1               ; Contract:
00EA17  1               ;   Description: Copies Inline Display Record.
00EA17  1               ;   Entry: Registers: A, X, Y; Memory: ($26), $26, $04, $27
00EA17  1               ;   Returns/products: Registers/clobbers: A, X, Y
00EA17  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00EA17  1               ;   Memory effects: $26, $27, $04, $0300
00EA17  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00EA17  1               ;          comparison, load, or store path and are not a stable API product.
00EA17  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 12.
00EA17  1               ; ----------------------------------------------------------------------------
00EA17  1               CopyInlineDisplayRecord:        ; $EA17
00EA17  1  20 3E EA         jsr AllocateDisplayBufferRecord                   ; $EA17: 20 3E EA
00EA1A  1                                               ; Reserve or initialize the destination record.
00EA1A  1                                               ; Returns the destination offset in X.
00EA1A  1               
00EA1A  1               ; ----------------------------------------------------------------------------
00EA1A  1               ; Remove the caller's return address from the stack.
00EA1A  1               ;
00EA1A  1               ; JSR stores the address of the final JSR operand byte. Therefore, inline byte
00EA1A  1               ; zero is found at offset one from the saved address.
00EA1A  1               ; ----------------------------------------------------------------------------
00EA1A  1               
00EA1A  1  68               pla                         ; $EA1A: 68
00EA1B  1  85 26            sta $26                     ; $EA1B: 85 26
00EA1D  1                                               ; Saved return-address low byte.
00EA1D  1               
00EA1D  1  68               pla                         ; $EA1D: 68
00EA1E  1  85 27            sta $27                     ; $EA1E: 85 27
00EA20  1                                               ; Saved return-address high byte.
00EA20  1               
00EA20  1               ; ----------------------------------------------------------------------------
00EA20  1               ; Read the inline byte count.
00EA20  1               ; ----------------------------------------------------------------------------
00EA20  1               
00EA20  1  A0 01            ldy #$01                    ; $EA20: A0 01
00EA22  1               
00EA22  1  B1 26            lda ($26),y                 ; $EA22: B1 26
00EA24  1  85 04            sta $04                     ; $EA24: 85 04
00EA26  1                                               ; Number of data bytes to copy.
00EA26  1               
00EA26  1               ; ----------------------------------------------------------------------------
00EA26  1               ; Copy the inline data into the display buffer at $0300,X.
00EA26  1               ; ----------------------------------------------------------------------------
00EA26  1               
00EA26  1               CopyInlineDisplayRecord_Loop:   ; $EA26
00EA26  1  C8               iny                         ; $EA26: C8
00EA27  1                                               ; Advance to the next inline data byte.
00EA27  1               
00EA27  1  B1 26            lda ($26),y                 ; $EA27: B1 26
00EA29  1  9D 00 03         sta $0300,x                 ; $EA29: 9D 00 03
00EA2C  1               
00EA2C  1  E8               inx                         ; $EA2C: E8
00EA2D  1                                               ; Advance the destination offset.
00EA2D  1               
00EA2D  1  C6 04            dec $04                     ; $EA2D: C6 04
00EA2F  1  D0 F5            bne CopyInlineDisplayRecord_Loop
00EA31  1                                               ; $EA2F: D0 F5
00EA31  1               
00EA31  1               ; ----------------------------------------------------------------------------
00EA31  1               ; Advance the saved return address past the complete inline record.
00EA31  1               ;
00EA31  1               ; Y now equals:
00EA31  1               ;
00EA31  1               ;   byte count + 1
00EA31  1               ;
00EA31  1               ; Adding Y to the original return address produces the address of the final
00EA31  1               ; inline byte. RTS will increment that address and resume at the instruction
00EA31  1               ; immediately following the inline record.
00EA31  1               ; ----------------------------------------------------------------------------
00EA31  1               
00EA31  1  18               clc                         ; $EA31: 18
00EA32  1               
00EA32  1  98               tya                         ; $EA32: 98
00EA33  1  65 26            adc $26                     ; $EA33: 65 26
00EA35  1  A8               tay                         ; $EA35: A8
00EA36  1                                               ; Y = adjusted return-address low byte.
00EA36  1               
00EA36  1               ; ----------------------------------------------------------------------------
00EA36  1               ; $04 is zero after the copy loop. ADC therefore propagates only carry into
00EA36  1               ; the saved return-address high byte.
00EA36  1               ; ----------------------------------------------------------------------------
00EA36  1               
00EA36  1  A5 04            lda $04                     ; $EA36: A5 04
00EA38  1                                               ; A = $00.
00EA38  1               
00EA38  1  65 27            adc $27                     ; $EA38: 65 27
00EA3A  1                                               ; A = adjusted return-address high byte.
00EA3A  1               
00EA3A  1               ; ----------------------------------------------------------------------------
00EA3A  1               ; Rebuild the adjusted return address on the stack.
00EA3A  1               ;
00EA3A  1               ; RTS pulls low byte first, then high byte, so the high byte is pushed first.
00EA3A  1               ; ----------------------------------------------------------------------------
00EA3A  1               
00EA3A  1  48               pha                         ; $EA3A: 48
00EA3B  1                                               ; Push adjusted high byte.
00EA3B  1               
00EA3B  1  98               tya                         ; $EA3B: 98
00EA3C  1  48               pha                         ; $EA3C: 48
00EA3D  1                                               ; Push adjusted low byte.
00EA3D  1               
00EA3D  1  60               rts                         ; $EA3D: 60
00EA3E  1                                               ; Resume after the inline record.
00EA3E  1               
00EA3E  1               ; ============================================================================
00EA3E  1               ; $EA3E-$EA62
00EA3E  1               ; Allocate and initialize a variable-length record in the display buffer.
00EA3E  1               ;
00EA3E  1               ; Entry:
00EA3E  1               ;   A = record parameter stored at offset +1
00EA3E  1               ;   X = record parameter stored at offset +2
00EA3E  1               ;   Y = payload length
00EA3E  1               ;   C = Boolean flag encoded at offset +3
00EA3E  1               ;   $3E = current display-buffer write offset
00EA3E  1               ;
00EA3E  1               ; Record layout:
00EA3E  1               ;
00EA3E  1               ;   +0 = payload length
00EA3E  1               ;   +1 = incoming A
00EA3E  1               ;   +2 = incoming X
00EA3E  1               ;   +3 = incoming carry encoded as $00 or $04
00EA3E  1               ;   +4 = beginning of payload
00EA3E  1               ;
00EA3E  1               ; Exit:
00EA3E  1               ;   X = payload destination offset
00EA3E  1               ;   $3E = next free record offset
00EA3E  1               ; ============================================================================
00EA3E  1               
00EA3E  1               ; ----------------------------------------------------------------------------
00EA3E  1               ; Contract:
00EA3E  1               ;   Description: Implements Allocate Display Buffer Record.
00EA3E  1               ;   Entry: Registers: A, X, Y; Memory: $3e, $06, $05
00EA3E  1               ;   Returns/products: Registers/clobbers: A, X, Y
00EA3E  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00EA3E  1               ;   Memory effects: $05, $06, $0301, $0302, $0303, $0300, $3e
00EA3E  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00EA3E  1               ;          comparison, load, or store path and are not a stable API product.
00EA3E  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 11.
00EA3E  1               ; ----------------------------------------------------------------------------
00EA3E  1               AllocateDisplayBufferRecord:    ; $EA3E
00EA3E  1  84 05            sty $05                     ; $EA3E: 84 05
00EA40  1                                               ; Save payload length.
00EA40  1               
00EA40  1  A0 00            ldy #$00                    ; $EA40: A0 00
00EA42  1  84 06            sty $06                     ; $EA42: 84 06
00EA44  1                                               ; Clear flag accumulator without changing C.
00EA44  1               
00EA44  1  A4 3E            ldy PpuQueueOffset                     ; $EA44: A4 3E
00EA46  1                                               ; Y = current record offset.
00EA46  1               
00EA46  1               ; ----------------------------------------------------------------------------
00EA46  1               ; Store the caller parameters.
00EA46  1               ; ----------------------------------------------------------------------------
00EA46  1               
00EA46  1  99 01 03         sta $0301,y                 ; $EA46: 99 01 03
00EA49  1                                               ; Record byte +1 = incoming A.
00EA49  1               
00EA49  1  8A               txa                         ; $EA49: 8A
00EA4A  1  99 02 03         sta $0302,y                 ; $EA4A: 99 02 03
00EA4D  1                                               ; Record byte +2 = incoming X.
00EA4D  1               
00EA4D  1               ; ----------------------------------------------------------------------------
00EA4D  1               ; Encode incoming carry as bit two:
00EA4D  1               ;
00EA4D  1               ;   C clear -> $00
00EA4D  1               ;   C set   -> $04
00EA4D  1               ;
00EA4D  1               ; LDA preserves carry. Starting from zero, three ROL instructions move the
00EA4D  1               ; incoming carry into bit two.
00EA4D  1               ; ----------------------------------------------------------------------------
00EA4D  1               
00EA4D  1  A5 06            lda $06                     ; $EA4D: A5 06
00EA4F  1  2A               rol                         ; $EA4F: 2A
00EA50  1  2A               rol                         ; $EA50: 2A
00EA51  1  2A               rol                         ; $EA51: 2A
00EA52  1               
00EA52  1  99 03 03         sta $0303,y                 ; $EA52: 99 03 03
00EA55  1                                               ; Record byte +3 = encoded flag.
00EA55  1               
00EA55  1               ; ----------------------------------------------------------------------------
00EA55  1               ; Store the payload length as record byte zero.
00EA55  1               ; ----------------------------------------------------------------------------
00EA55  1               
00EA55  1  A5 05            lda $05                     ; $EA55: A5 05
00EA57  1  99 00 03         sta $0300,y                 ; $EA57: 99 00 03
00EA5A  1               
00EA5A  1               ; ----------------------------------------------------------------------------
00EA5A  1               ; Calculate the payload destination:
00EA5A  1               ;
00EA5A  1               ;   X = record offset + 4
00EA5A  1               ; ----------------------------------------------------------------------------
00EA5A  1               
00EA5A  1  98               tya                         ; $EA5A: 98
00EA5B  1  69 04            adc #$04                    ; $EA5B: 69 04
00EA5D  1  AA               tax                         ; $EA5D: AA
00EA5E  1                                               ; X points to the payload area.
00EA5E  1                                               ;
00EA5E  1                                               ; Carry is normally clear after the third ROL:
00EA5E  1                                               ; the original carry has moved into bit two.
00EA5E  1               
00EA5E  1               ; ----------------------------------------------------------------------------
00EA5E  1               ; Calculate the next free record offset:
00EA5E  1               ;
00EA5E  1               ;   $3E = payload offset + payload length
00EA5E  1               ; ----------------------------------------------------------------------------
00EA5E  1               
00EA5E  1  65 05            adc $05                     ; $EA5E: 65 05
00EA60  1  85 3E            sta PpuQueueOffset                     ; $EA60: 85 3E
00EA62  1               
00EA62  1  60               rts                         ; $EA62: 60
00EA63  1               
00EA63  1               ; ============================================================================
00EA63  1               ; $EA63-$EAAE
00EA63  1               ; Decode and render an inline stream of PPU transfer records.
00EA63  1               ;
00EA63  1               ; The routine obtains an inline pointer through DecodeInlineParameters and
00EA63  1               ; processes records until a zero terminator is encountered.
00EA63  1               ;
00EA63  1               ; Initial decoded values:
00EA63  1               ;   X = stream pointer low byte
00EA63  1               ;   A = stream pointer high byte
00EA63  1               ;
00EA63  1               ; Stream record format:
00EA63  1               ;
00EA63  1               ;   byte 0:
00EA63  1               ;       PPU address high byte
00EA63  1               ;
00EA63  1               ;   byte 1:
00EA63  1               ;       PPU address low byte
00EA63  1               ;
00EA63  1               ;   byte 2:
00EA63  1               ;       control byte
00EA63  1               ;
00EA63  1               ;   remaining bytes:
00EA63  1               ;       one literal byte or one repeated byte, according to the control byte
00EA63  1               ;
00EA63  1               ; A zero byte at the start of the next record terminates the stream.
00EA63  1               ; ============================================================================
00EA63  1               
00EA63  1               ; ----------------------------------------------------------------------------
00EA63  1               ; Contract:
00EA63  1               ;   Description: Processes Inline Ppu Stream.
00EA63  1               ;   Entry: Registers: A, X, Y; Memory: ($08), $08, $09, $2002
00EA63  1               ;   Returns/products: Registers/clobbers: A, X, Y
00EA63  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00EA63  1               ;   Memory effects: $09, $08, $2006, $2000, $2007
00EA63  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00EA63  1               ;          comparison, load, or store path and are not a stable API product.
00EA63  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 3.
00EA63  1               ; ----------------------------------------------------------------------------
00EA63  1               ProcessInlinePpuStream:         ; $EA63
00EA63  1  20 9A E9         jsr DecodeInlineParameters ; $EA63: 20 9A E9
00EA66  1                                              ; X = stream-pointer low byte
00EA66  1                                              ; A = stream-pointer high byte
00EA66  1               
00EA66  1  85 09            sta $09                    ; $EA66: 85 09
00EA68  1                                              ; Save stream-pointer high byte.
00EA68  1               
00EA68  1  86 08            stx $08                    ; $EA68: 86 08
00EA6A  1                                              ; Save stream-pointer low byte.
00EA6A  1               
00EA6A  1               ; ----------------------------------------------------------------------------
00EA6A  1               ; A nonzero high byte skips directly to the initial terminator check.
00EA6A  1               ;
00EA6A  1               ; A zero high byte falls through and processes the first record using A as the
00EA6A  1               ; first PPU address byte. This dual entry behavior is intentional.
00EA6A  1               ; ----------------------------------------------------------------------------
00EA6A  1               
00EA6A  1  D0 37            bne ProcessInlinePpuStream_CheckRecord
00EA6C  1                                              ; $EA6A: D0 37
00EA6C  1               
00EA6C  1               ; ============================================================================
00EA6C  1               ; $EA6C
00EA6C  1               ; Process one PPU transfer record.
00EA6C  1               ; ============================================================================
00EA6C  1               
00EA6C  1               ProcessInlinePpuStream_Record:  ; $EA6C
00EA6C  1  8D 06 20         sta $2006                   ; $EA6C: 8D 06 20
00EA6F  1                                               ; Write PPU address high byte.
00EA6F  1               
00EA6F  1  C8               iny                         ; $EA6F: C8
00EA70  1               
00EA70  1  B1 08            lda ($08),y                 ; $EA70: B1 08
00EA72  1  8D 06 20         sta $2006                   ; $EA72: 8D 06 20
00EA75  1                                               ; Write PPU address low byte.
00EA75  1               
00EA75  1               ; ----------------------------------------------------------------------------
00EA75  1               ; Read and preserve the record control byte.
00EA75  1               ; ----------------------------------------------------------------------------
00EA75  1               
00EA75  1  C8               iny                         ; $EA75: C8
00EA76  1               
00EA76  1  B1 08            lda ($08),y                 ; $EA76: B1 08
00EA78  1  0A               asl                         ; $EA78: 0A
00EA79  1  48               pha                         ; $EA79: 48
00EA7A  1                                               ; Preserve shifted control byte.
00EA7A  1               
00EA7A  1               ; ----------------------------------------------------------------------------
00EA7A  1               ; Derive PPUCTRL bit two from the original control-byte high bit.
00EA7A  1               ;
00EA7A  1               ; After ASL, the original bit seven is in carry. Beginning with zero, three
00EA7A  1               ; ROL instructions move that carry into bit two.
00EA7A  1               ; ----------------------------------------------------------------------------
00EA7A  1               
00EA7A  1  A9 00            lda #$00                    ; $EA7A: A9 00
00EA7C  1  2A               rol                         ; $EA7C: 2A
00EA7D  1  2A               rol                         ; $EA7D: 2A
00EA7E  1  2A               rol                         ; $EA7E: 2A
00EA7F  1               
00EA7F  1  8D 00 20         sta $2000                   ; $EA7F: 8D 00 20
00EA82  1                                               ; Select PPU address increment mode.
00EA82  1               
00EA82  1               ; ----------------------------------------------------------------------------
00EA82  1               ; Restore and further decode the shifted control byte.
00EA82  1               ; ----------------------------------------------------------------------------
00EA82  1               
00EA82  1  68               pla                         ; $EA82: 68
00EA83  1  0A               asl                         ; $EA83: 0A
00EA84  1                                               ; Carry receives the next control flag.
00EA84  1               
00EA84  1  90 03            bcc ProcessInlinePpuStream_DecodeCount
00EA86  1                                               ; $EA84: 90 03
00EA86  1               
00EA86  1               ; ----------------------------------------------------------------------------
00EA86  1               ; Repeated-value mode.
00EA86  1               ;
00EA86  1               ; Set bit one in the working control byte and advance Y so the same source byte
00EA86  1               ; can be written repeatedly.
00EA86  1               ; ----------------------------------------------------------------------------
00EA86  1               
00EA86  1  09 02            ora #$02                    ; $EA86: 09 02
00EA88  1  C8               iny                         ; $EA88: C8
00EA89  1               
00EA89  1               ; ----------------------------------------------------------------------------
00EA89  1               ; Divide the working control byte by four.
00EA89  1               ;
00EA89  1               ; Exit:
00EA89  1               ;   X = transfer count
00EA89  1               ;   Carry = literal/repeated source-advance flag
00EA89  1               ; ----------------------------------------------------------------------------
00EA89  1               
00EA89  1               ProcessInlinePpuStream_DecodeCount: ; $EA89
00EA89  1  4A               lsr                         ; $EA89: 4A
00EA8A  1  4A               lsr                         ; $EA8A: 4A
00EA8B  1  AA               tax                         ; $EA8B: AA
00EA8C  1               
00EA8C  1               ; ============================================================================
00EA8C  1               ; $EA8C
00EA8C  1               ; Write the current record's payload to PPUDATA.
00EA8C  1               ;
00EA8C  1               ; Carry controls whether the source pointer advances for each output byte:
00EA8C  1               ;
00EA8C  1               ;   C clear -> increment Y before reading
00EA8C  1               ;   C set   -> reuse the same source byte
00EA8C  1               ; ============================================================================
00EA8C  1               
00EA8C  1               ProcessInlinePpuStream_WriteLoop: ; $EA8C
00EA8C  1  B0 01            bcs ProcessInlinePpuStream_Write
00EA8E  1                                               ; $EA8C: B0 01
00EA8E  1               
00EA8E  1  C8               iny                         ; $EA8E: C8
00EA8F  1               
00EA8F  1               ProcessInlinePpuStream_Write:   ; $EA8F
00EA8F  1  B1 08            lda ($08),y                 ; $EA8F: B1 08
00EA91  1  8D 07 20         sta $2007                   ; $EA91: 8D 07 20
00EA94  1               
00EA94  1  CA               dex                         ; $EA94: CA
00EA95  1  D0 F5            bne ProcessInlinePpuStream_WriteLoop
00EA97  1                                               ; $EA95: D0 F5
00EA97  1               
00EA97  1               ; ----------------------------------------------------------------------------
00EA97  1               ; Advance the stream pointer past the record just processed.
00EA97  1               ;
00EA97  1               ; Y is the final source index consumed. Increment it, then add it to $08/$09.
00EA97  1               ; ----------------------------------------------------------------------------
00EA97  1               
00EA97  1  C8               iny                         ; $EA97: C8
00EA98  1               
00EA98  1  18               clc                         ; $EA98: 18
00EA99  1               
00EA99  1  98               tya                         ; $EA99: 98
00EA9A  1  65 08            adc $08                     ; $EA9A: 65 08
00EA9C  1  85 08            sta $08                     ; $EA9C: 85 08
00EA9E  1               
00EA9E  1  8A               txa                         ; $EA9E: 8A
00EA9F  1                                               ; X is zero after the transfer loop.
00EA9F  1               
00EA9F  1  65 09            adc $09                     ; $EA9F: 65 09
00EAA1  1  85 09            sta $09                     ; $EAA1: 85 09
00EAA3  1               
00EAA3  1               ; ============================================================================
00EAA3  1               ; $EAA3
00EAA3  1               ; Check the next record for the zero terminator.
00EAA3  1               ; ============================================================================
00EAA3  1               
00EAA3  1               ProcessInlinePpuStream_CheckRecord: ; $EAA3
00EAA3  1  AE 02 20         ldx $2002                   ; $EAA3: AE 02 20
00EAA6  1                                               ; Reset PPU address latch.
00EAA6  1                                               ; The status value itself is unused.
00EAA6  1               
00EAA6  1  A0 00            ldy #$00                    ; $EAA6: A0 00
00EAA8  1               
00EAA8  1  B1 08            lda ($08),y                 ; $EAA8: B1 08
00EAAA  1  D0 C0            bne ProcessInlinePpuStream_Record
00EAAC  1                                               ; $EAAA: D0 C0
00EAAC  1               
00EAAC  1               ; ----------------------------------------------------------------------------
00EAAC  1               ; End of stream.
00EAAC  1               ;
00EAAC  1               ; Return Y=$03, matching the inline-record convention used by nearby helpers.
00EAAC  1               ; ----------------------------------------------------------------------------
00EAAC  1               
00EAAC  1  A0 03            ldy #$03                    ; $EAAC: A0 03
00EAAE  1  60               rts                         ; $EAAE: 60
00EAAF  1               
00EAAF  1               ; ============================================================================
00EAAF  1               ; $EAAF-$EAF4
00EAAF  1               ; Run a complete display or screen transition.
00EAAF  1               ;
00EAAF  1               ; Entry:
00EAAF  1               ;   Y = $03
00EAAF  1               ;
00EAAF  1               ; The preceding PPU stream routine returns with Y set to $03. This routine
00EAAF  1               ; saves that value in $E4 and uses it during the transition.
00EAAF  1               ; ============================================================================
00EAAF  1               
00EAAF  1               RunDisplayTransition:           ; $EAAF
00EAAF  1  84 E4            sty $E4                     ; $EAAF: 84 E4
00EAB1  1               
00EAB1  1  20 66 EB         jsr DispatchNextQueuedEvent                   ; $EAB1: 20 66 EB
00EAB4  1  20 4C EB         jsr SelectObjectEventBank0                   ; $EAB4: 20 4C EB
00EAB7  1  20 9D EB         jsr InitializeQueuedEventSystem                   ; $EAB7: 20 9D EB
00EABA  1               
00EABA  1  20 6C E9         jsr DisablePpuRendering     ; $EABA: 20 6C E9
00EABD  1               
00EABD  1               ; ----------------------------------------------------------------------------
00EABD  1               ; Set PPU address $2324.
00EABD  1               ; ----------------------------------------------------------------------------
00EABD  1               
00EABD  1  20 DB E9         jsr SetPpuAddressFromInlineRecord
00EAC0  1                                               ; $EABD: 20 DB E9
00EAC0  1               
00EAC0  1  24 23            .byte $24,$23               ; $EAC0-$EAC1
00EAC2  1               
00EAC2  1  A5 E4            lda $E4                     ; $EAC2: A5 E4
00EAC4  1  20 00 EB         jsr WriteGeneratedPpuWord                   ; $EAC4: 20 00 EB
00EAC7  1               
00EAC7  1               ; ----------------------------------------------------------------------------
00EAC7  1               ; Set PPU address $2B24.
00EAC7  1               ; ----------------------------------------------------------------------------
00EAC7  1               
00EAC7  1  20 DB E9         jsr SetPpuAddressFromInlineRecord
00EACA  1                                               ; $EAC7: 20 DB E9
00EACA  1               
00EACA  1  24 2B            .byte $24,$2B               ; $EACA-$EACB
00EACC  1               
00EACC  1  A5 E4            lda $E4                     ; $EACC: A5 E4
00EACE  1  20 00 EB         jsr WriteGeneratedPpuWord                   ; $EACE: 20 00 EB
00EAD1  1               
00EAD1  1               ; ----------------------------------------------------------------------------
00EAD1  1               ; Set PPU address $2337.
00EAD1  1               ; ----------------------------------------------------------------------------
00EAD1  1               
00EAD1  1  20 DB E9         jsr SetPpuAddressFromInlineRecord
00EAD4  1                                               ; $EAD1: 20 DB E9
00EAD4  1               
00EAD4  1  37 23            .byte $37,$23               ; $EAD4-$EAD5
00EAD6  1               
00EAD6  1  20 F5 EA         jsr WriteFixedPpuSequence                   ; $EAD6: 20 F5 EA
00EAD9  1               
00EAD9  1               ; ----------------------------------------------------------------------------
00EAD9  1               ; Set PPU address $2B37.
00EAD9  1               ; ----------------------------------------------------------------------------
00EAD9  1               
00EAD9  1  20 DB E9         jsr SetPpuAddressFromInlineRecord
00EADC  1                                               ; $EAD9: 20 DB E9
00EADC  1               
00EADC  1  37 2B            .byte $37,$2B               ; $EADC-$EADD
00EADE  1               
00EADE  1  20 F5 EA         jsr WriteFixedPpuSequence                   ; $EADE: 20 F5 EA
00EAE1  1               
00EAE1  1               ; ----------------------------------------------------------------------------
00EAE1  1               ; Initialize the next transition phase.
00EAE1  1               ; ----------------------------------------------------------------------------
00EAE1  1               
00EAE1  1  A9 0A            lda #$0A                    ; $EAE1: A9 0A
00EAE3  1  85 DE            sta PpuMaskShadow                     ; $EAE3: 85 DE
00EAE5  1               
00EAE5  1               ; ----------------------------------------------------------------------------
00EAE5  1               ; Reset the PPU address latch, enable NMI, and wait for a frame.
00EAE5  1               ; ----------------------------------------------------------------------------
00EAE5  1               
00EAE5  1  20 78 E9         jsr EnableNmiAndWaitForFrame
00EAE8  1                                               ; $EAE5: 20 78 E9
00EAE8  1               
00EAE8  1               ; ----------------------------------------------------------------------------
00EAE8  1               ; Perform two waits using delay value $FF.
00EAE8  1               ; ----------------------------------------------------------------------------
00EAE8  1               
00EAE8  1  A9 FF            lda #$FF                    ; $EAE8: A9 FF
00EAEA  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $EAEA: 20 41 EB
00EAED  1               
00EAED  1  A9 FF            lda #$FF                    ; $EAED: A9 FF
00EAEF  1  20 41 EB         jsr StoreObjectEventBankValue                   ; $EAEF: 20 41 EB
00EAF2  1               
00EAF2  1               ; ----------------------------------------------------------------------------
00EAF2  1               ; Transfer to the common display-transition continuation.
00EAF2  1               ; ----------------------------------------------------------------------------
00EAF2  1               
00EAF2  1  4C 0B C4         jmp Reset                   ; $EAF2: 4C 0B C4
00EAF5  1               
00EAF5  1               ; ============================================================================
00EAF5  1               ; $EAF5-$EAFF
00EAF5  1               ; Write a fixed six-byte sequence to PPUDATA.
00EAF5  1               ;
00EAF5  1               ; Entry:
00EAF5  1               ;   The caller has already selected the destination PPU address through
00EAF5  1               ;   SetPpuAddressFromInlineRecord.
00EAF5  1               ;
00EAF5  1               ; This routine enters WriteInlinePpuBlock at its internal $EA05 entry,
00EAF5  1               ; skipping the PPU-address setup call at $EA02.
00EAF5  1               ;
00EAF5  1               ; Inline record:
00EAF5  1               ;
00EAF5  1               ;   byte 0 = transfer count, $06
00EAF5  1               ;   bytes 1-6 = PPU data:
00EAF5  1               ;       $0C,$0A,$15,$15,$0E,$0D
00EAF5  1               ;
00EAF5  1               ; WriteInlinePpuBlock adjusts the return address past the inline data, so
00EAF5  1               ; execution resumes at the RTS at $EAFF.
00EAF5  1               ; ============================================================================
00EAF5  1               
00EAF5  1               ; ----------------------------------------------------------------------------
00EAF5  1               ; Contract:
00EAF5  1               ;   Description: Writes Fixed Ppu Sequence.
00EAF5  1               ;   Entry: No register input inferred
00EAF5  1               ;   Returns/products: No direct product inferred
00EAF5  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00EAF5  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00EAF5  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00EAF5  1               ;          comparison, load, or store path and are not a stable API product.
00EAF5  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 2.
00EAF5  1               ; ----------------------------------------------------------------------------
00EAF5  1               WriteFixedPpuSequence:          ; $EAF5
00EAF5  1  20 05 EA         jsr WriteInlinePpuBlockAfterAddress                   ; $EAF5: 20 05 EA
00EAF8  1                                               ; Internal entry in WriteInlinePpuBlock.
00EAF8  1                                               ;
00EAF8  1                                               ; $EA05: STX $05
00EAF8  1                                               ; $EA07: JSR DecodeInlineParameters
00EAF8  1               
00EAF8  1               ; ----------------------------------------------------------------------------
00EAF8  1               ; Inline transfer record consumed by the helper at $EA05.
00EAF8  1               ; ----------------------------------------------------------------------------
00EAF8  1               
00EAF8  1  06               .byte $06                   ; $EAF8
00EAF9  1                                               ; Number of bytes to write.
00EAF9  1               
00EAF9  1  0C 0A 15         .byte $0C,$0A,$15           ; $EAF9-$EAFB
00EAFC  1  15 0E 0D         .byte $15,$0E,$0D           ; $EAFC-$EAFE
00EAFF  1               
00EAFF  1               ; ----------------------------------------------------------------------------
00EAFF  1               ; Execution resumes here after the inline record has been consumed.
00EAFF  1               ; ----------------------------------------------------------------------------
00EAFF  1               
00EAFF  1  60               rts                         ; $EAFF: 60
00EB00  1               
00EB00  1               ; ============================================================================
00EB00  1               ; $EB00-$EB0A
00EB00  1               ; Generate a two-byte value through $D01D and write both bytes to PPUDATA.
00EB00  1               ;
00EB00  1               ; The helper at $D01D returns:
00EB00  1               ;
00EB00  1               ;   Y = first byte
00EB00  1               ;   A = second byte
00EB00  1               ;
00EB00  1               ; Both values are written consecutively to the current PPU address.
00EB00  1               ; ============================================================================
00EB00  1               
00EB00  1               ; ----------------------------------------------------------------------------
00EB00  1               ; Contract:
00EB00  1               ;   Description: Writes Generated Ppu Word.
00EB00  1               ;   Entry: Registers: A, Y
00EB00  1               ;   Returns/products: Primary products are committed to memory.
00EB00  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00EB00  1               ;   Memory effects: ppudata
00EB00  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00EB00  1               ;          comparison, load, or store path and are not a stable API product.
00EB00  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 2.
00EB00  1               ; ----------------------------------------------------------------------------
00EB00  1               WriteGeneratedPpuWord:          ; $EB00
00EB00  1  20 1D D0         jsr DivideABy10                   ; $EB00: 20 1D D0
00EB03  1                                               ; Generate or retrieve a two-byte value.
00EB03  1                                               ;
00EB03  1                                               ; Return:
00EB03  1                                               ;   Y = first byte
00EB03  1                                               ;   A = second byte
00EB03  1               
00EB03  1               ; ----------------------------------------------------------------------------
00EB03  1               ; Write the first byte returned in Y.
00EB03  1               ; ----------------------------------------------------------------------------
00EB03  1               
00EB03  1  8C 07 20         sty PPUDATA                  ; $EB03: 8C 07 20
00EB06  1               
00EB06  1               ; ----------------------------------------------------------------------------
00EB06  1               ; Write the second byte returned in A.
00EB06  1               ; ----------------------------------------------------------------------------
00EB06  1               
00EB06  1  8D 07 20         sta PPUDATA                 ; $EB06: 8D 07 20
00EB09  1               
00EB09  1  60               rts                         ; $EB09: 60
00EB0A  1               
00EB0A  1               ; ============================================================================
00EB0A  1               ; $EB0A-$EB29
00EB0A  1               ; Decode an inline event record, update the event arrays for object X, and
00EB0A  1               ; either start the display transition immediately or enqueue the object.
00EB0A  1               ;
00EB0A  1               ; Entry:
00EB0A  1               ;   X = object/event index
00EB0A  1               ;
00EB0A  1               ; Inline record:
00EB0A  1               ;   byte 0 = value stored in $069F,X
00EB0A  1               ;   byte 1 = value stored in $06CF,X
00EB0A  1               ;
00EB0A  1               ; DecodeInlineParameters returns:
00EB0A  1               ;   X = first inline byte
00EB0A  1               ;   A = second inline byte
00EB0A  1               ;   Y = index into the caller's inline record
00EB0A  1               ;
00EB0A  1               ; Important:
00EB0A  1               ;   This routine is also entered internally at $EB0D by the helper at $E29B.
00EB0A  1               ;   That entry skips DecodeInlineParameters because $E99A was already called.
00EB0A  1               ; ============================================================================
00EB0A  1               
00EB0A  1               ; ----------------------------------------------------------------------------
00EB0A  1               ; Contract:
00EB0A  1               ;   Description: Queues Inline Object Event.
00EB0A  1               ;   Entry: Registers: A, X, Y; Memory: ($00), $06ff, $e2
00EB0A  1               ;   Returns/products: Registers/clobbers: A, Y
00EB0A  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00EB0A  1               ;   Memory effects: $069f, $06cf, $06ff, $0670
00EB0A  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00EB0A  1               ;          comparison, load, or store path and are not a stable API product.
00EB0A  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 45.
00EB0A  1               ; ----------------------------------------------------------------------------
00EB0A  1               QueueInlineObjectEvent:         ; $EB0A
00EB0A  1  20 9A E9         jsr DecodeInlineParameters  ; $EB0A: 20 9A E9
00EB0D  1               
00EB0D  1               ; ============================================================================
00EB0D  1               ; $EB0D
00EB0D  1               ; Internal entry used by DispatchInlineObjectCommand at $E29B.
00EB0D  1               ;
00EB0D  1               ; Entry:
00EB0D  1               ;   X = object/event index restored by $E29B
00EB0D  1               ;   A = second decoded inline byte
00EB0D  1               ;   Y = inline source index established by DecodeInlineParameters
00EB0D  1               ;   $00/$01 = pointer to the inline record
00EB0D  1               ; ============================================================================
00EB0D  1               
00EB0D  1               QueueDecodedObjectEvent:        ; $EB0D
00EB0D  1  9D 9F 06         sta $069F,x                 ; $EB0D: 9D 9F 06
00EB10  1                                               ; Save the second inline parameter.
00EB10  1               
00EB10  1  B1 00            lda ($00),y                 ; $EB10: B1 00
00EB12  1                                               ; Load the next inline byte.
00EB12  1               
00EB12  1  9D CF 06         sta $06CF,x                 ; $EB12: 9D CF 06
00EB15  1                                               ; Save it in the parallel event array.
00EB15  1               
00EB15  1               ; ----------------------------------------------------------------------------
00EB15  1               ; Use the object/event index as an index into the active-event array.
00EB15  1               ; ----------------------------------------------------------------------------
00EB15  1               
00EB15  1               ; ----------------------------------------------------------------------------
00EB15  1               ; Contract:
00EB15  1               ;   Description: Internal event-queue entry after inline values have been stored.
00EB15  1               ;   Entry: X = object/event index.
00EB15  1               ;   Returns/products: Queues or dispatches event context.
00EB15  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00EB15  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00EB15  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00EB15  1               ;          comparison, load, or store path and are not a stable API product.
00EB15  1               ;   Validation: Internal-entry contract; call sites: internal entry.
00EB15  1               ; ----------------------------------------------------------------------------
00EB15  1               QueueDecodedObjectEventSelectIndex:
00EB15  1  8A               txa                         ; $EB15: 8A
00EB16  1               ; ----------------------------------------------------------------------------
00EB16  1               ; Contract:
00EB16  1               ;   Description: Internal event-queue entry with object index transferred to Y.
00EB16  1               ;   Entry: X/Y identify object/event entry.
00EB16  1               ;   Returns/products: Queues or dispatches event context.
00EB16  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00EB16  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00EB16  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00EB16  1               ;          comparison, load, or store path and are not a stable API product.
00EB16  1               ;   Validation: Internal-entry contract; call sites: internal entry.
00EB16  1               ; ----------------------------------------------------------------------------
00EB16  1               QueueDecodedObjectEventCheckActive:
00EB16  1  A8               tay                         ; $EB16: A8
00EB17  1               
00EB17  1  B9 FF 06         lda $06FF,y                 ; $EB17: B9 FF 06
00EB1A  1  D0 93            bne RunDisplayTransition    ; $EB1A: D0 93
00EB1C  1                                               ; Target $EAAF.
00EB1C  1                                               ;
00EB1C  1                                               ; If the object already has a nonzero active
00EB1C  1                                               ; entry, immediately run the display transition.
00EB1C  1               
00EB1C  1               ; ----------------------------------------------------------------------------
00EB1C  1               ; Mark this object/event entry active.
00EB1C  1               ;
00EB1C  1               ; A is zero here because the preceding BNE was not taken. TYA restores the
00EB1C  1               ; object index, which is stored in the active-event array.
00EB1C  1               ; ----------------------------------------------------------------------------
00EB1C  1               
00EB1C  1  98               tya                         ; $EB1C: 98
00EB1D  1  99 FF 06         sta $06FF,y                 ; $EB1D: 99 FF 06
00EB20  1               
00EB20  1               ; ----------------------------------------------------------------------------
00EB20  1               ; Append the object/event index to the queue at $0670.
00EB20  1               ;
00EB20  1               ; $E2 is the current queue length or next free queue slot.
00EB20  1               ; ----------------------------------------------------------------------------
00EB20  1               
00EB20  1  A4 E2            ldy $E2                     ; $EB20: A4 E2
00EB22  1  E6 E2            inc $E2                     ; $EB22: E6 E2
00EB24  1               
00EB24  1  99 70 06         sta $0670,y                 ; $EB24: 99 70 06
00EB27  1               
00EB27  1               ; ----------------------------------------------------------------------------
00EB27  1               ; Return Y=$04. Nearby inline-data and event helpers use this value as their
00EB27  1               ; resume/index convention.
00EB27  1               ; ----------------------------------------------------------------------------
00EB27  1               
00EB27  1  A0 04            ldy #$04                    ; $EB27: A0 04
00EB29  1  60               rts                         ; $EB29: 60
00EB2A  1               
00EB2A  1               ; ============================================================================
00EB2A  1               ; $EB2A-$EB3A
00EB2A  1               ; Process an active queued-event entry until its event-state byte becomes zero.
00EB2A  1               ;
00EB2A  1               ; Entry:
00EB2A  1               ;   X = object/event index
00EB2A  1               ;
00EB2A  1               ; Event arrays:
00EB2A  1               ;   $0600,X = active event identifier or state
00EB2A  1               ;   $060F,Y = event-state table inspected after processing
00EB2A  1               ;
00EB2A  1               ; Behavior:
00EB2A  1               ;   If $0600,X is already zero, return immediately.
00EB2A  1               ;
00EB2A  1               ;   Otherwise:
00EB2A  1               ;     1. Call the event-processing entry at $EB16.
00EB2A  1               ;     2. Use the returned value in A as an index into $060F.
00EB2A  1               ;     3. Repeat while the indexed event-state byte remains nonzero.
00EB2A  1               ;     4. Clear $0600,X when processing completes.
00EB2A  1               ; ============================================================================
00EB2A  1               
00EB2A  1               ; ----------------------------------------------------------------------------
00EB2A  1               ; Contract:
00EB2A  1               ;   Description: Processes Queued Object Event.
00EB2A  1               ;   Entry: Registers: A; Memory: $0600, $060f
00EB2A  1               ;   Returns/products: Registers/clobbers: A, Y
00EB2A  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00EB2A  1               ;   Memory effects: $0600
00EB2A  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00EB2A  1               ;          comparison, load, or store path and are not a stable API product.
00EB2A  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 5.
00EB2A  1               ; ----------------------------------------------------------------------------
00EB2A  1               ProcessQueuedObjectEvent:       ; $EB2A
00EB2A  1  BD 00 06         lda $0600,x                 ; $EB2A: BD 00 06
00EB2D  1  F0 0C            beq ProcessQueuedObjectEvent_Return
00EB2F  1                                               ; $EB2D: F0 0C
00EB2F  1               
00EB2F  1               ProcessQueuedObjectEvent_Loop:  ; $EB2F
00EB2F  1  20 16 EB         jsr QueueDecodedObjectEventCheckActive                   ; $EB2F: 20 16 EB
00EB32  1               
00EB32  1  A8               tay                         ; $EB32: A8
00EB33  1               
00EB33  1  B9 0F 06         lda $060F,y                 ; $EB33: B9 0F 06
00EB36  1  D0 F7            bne ProcessQueuedObjectEvent_Loop
00EB38  1                                               ; $EB36: D0 F7
00EB38  1               
00EB38  1  9D 00 06         sta $0600,x                 ; $EB38: 9D 00 06
00EB3B  1                                               ; Clear the entry with A=$00.
00EB3B  1               
00EB3B  1               ProcessQueuedObjectEvent_Return: ; $EB3B
00EB3B  1  60               rts                         ; $EB3B: 60
00EB3C  1               ; ============================================================================
00EB3C  1               ; $EB3C-$EB64
00EB3C  1               ; Update the current object's queue-bank selection and restore two saved event
00EB3C  1               ; values from the stack.
00EB3C  1               ;
00EB3C  1               ; Entry:
00EB3C  1               ;   A = value used to derive an index relative to $E3
00EB3C  1               ;   C = significant input to SBC
00EB3C  1               ;   $E1 = current object/event index
00EB3C  1               ;
00EB3C  1               ; The routine:
00EB3C  1               ;   1. Calculates a three-bit value and stores it in $063F,Y.
00EB3C  1               ;   2. Selects queue bank zero or one.
00EB3C  1               ;   3. Exchanges the current object's $060F entry with the selected bank's
00EB3C  1               ;      $0600 entry.
00EB3C  1               ;   4. Restores values from the stack into $069F,Y and $06CF,Y.
00EB3C  1               ;   5. Branches to the common engine exit at $EB6A.
00EB3C  1               ; ============================================================================
00EB3C  1               
00EB3C  1               UpdateObjectEventBank:          ; $EB3C
00EB3C  1  38               sec                         ; $EB3C: 38
00EB3D  1               
00EB3D  1  E5 E3            sbc FrameCounter                     ; $EB3D: E5 E3
00EB3F  1                                               ; Calculate a value relative to the current
00EB3F  1                                               ; event/queue state.
00EB3F  1               
00EB3F  1  29 07            and #$07                    ; $EB3F: 29 07
00EB41  1                                               ; Limit the result to three bits.
00EB41  1               
00EB41  1               ; ----------------------------------------------------------------------------
00EB41  1               ; Contract:
00EB41  1               ;   Description: Internal event-bank entry after the three-bit value is prepared in A.
00EB41  1               ;   Entry: A = event-bank value; current object index set.
00EB41  1               ;   Returns/products: $063F,Y updated; may continue into bank exchange.
00EB41  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00EB41  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00EB41  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00EB41  1               ;          comparison, load, or store path and are not a stable API product.
00EB41  1               ;   Validation: Internal-entry contract; call sites: internal entry.
00EB41  1               ; ----------------------------------------------------------------------------
00EB41  1               StoreObjectEventBankValue:
00EB41  1  A4 E1            ldy CurrentObjectIndex      ; $EB41: A4 E1
00EB43  1               
00EB43  1  99 3F 06         sta $063F,y                 ; $EB43: 99 3F 06
00EB46  1                                               ; Save the calculated three-bit value.
00EB46  1               
00EB46  1               ; ----------------------------------------------------------------------------
00EB46  1               ; A nonzero calculated value skips the queue-bank exchange and proceeds
00EB46  1               ; directly to the stack-restoration path.
00EB46  1               ; ----------------------------------------------------------------------------
00EB46  1               
00EB46  1  D0 12            bne UpdateObjectEventBank_Restore
00EB48  1                                               ; $EB46: D0 12
00EB48  1               
00EB48  1               ; ============================================================================
00EB48  1               ; $EB48
00EB48  1               ; Select queue bank one.
00EB48  1               ;
00EB48  1               ; This address is also called directly throughout the ROM as a frame/event
00EB48  1               ; synchronization helper. The direct-entry behavior begins by selecting bank
00EB48  1               ; one and continues through the exchange below.
00EB48  1               ; ============================================================================
00EB48  1               
00EB48  1               ; ----------------------------------------------------------------------------
00EB48  1               ; Contract:
00EB48  1               ;   Description: Implements Select Object Event Bank 1.
00EB48  1               ;   Entry: Registers: A, Y; Memory: currentobjectindex, $0600
00EB48  1               ;   Returns/products: Registers/clobbers: A, X, Y
00EB48  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00EB48  1               ;   Memory effects: $060f, $0600, $069f, $06cf
00EB48  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00EB48  1               ;          comparison, load, or store path and are not a stable API product.
00EB48  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 42.
00EB48  1               ; ----------------------------------------------------------------------------
00EB48  1               SelectObjectEventBank1:         ; $EB48
00EB48  1  A2 01            ldx #$01                    ; $EB48: A2 01
00EB4A  1               
00EB4A  1  D0 02            bne UpdateObjectEventBank_Exchange
00EB4C  1                                               ; $EB4A: D0 02
00EB4C  1                                               ; Always taken because X is nonzero.
00EB4C  1               
00EB4C  1               ; ============================================================================
00EB4C  1               ; $EB4C
00EB4C  1               ; Select queue bank zero.
00EB4C  1               ;
00EB4C  1               ; This is another direct entry used elsewhere in the ROM.
00EB4C  1               ; ============================================================================
00EB4C  1               
00EB4C  1               ; ----------------------------------------------------------------------------
00EB4C  1               ; Contract:
00EB4C  1               ;   Description: Implements Select Object Event Bank 0.
00EB4C  1               ;   Entry: Registers: A, Y; Memory: currentobjectindex, $0600
00EB4C  1               ;   Returns/products: Registers/clobbers: A, X, Y
00EB4C  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00EB4C  1               ;   Memory effects: $060f, $0600, $069f, $06cf
00EB4C  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00EB4C  1               ;          comparison, load, or store path and are not a stable API product.
00EB4C  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 7.
00EB4C  1               ; ----------------------------------------------------------------------------
00EB4C  1               SelectObjectEventBank0:         ; $EB4C
00EB4C  1  A2 00            ldx #$00                    ; $EB4C: A2 00
00EB4E  1               
00EB4E  1               ; ----------------------------------------------------------------------------
00EB4E  1               ; Exchange the current object's $060F entry with the selected bank's $0600
00EB4E  1               ; entry.
00EB4E  1               ;
00EB4E  1               ; Before:
00EB4E  1               ;   A = $0600,X
00EB4E  1               ;   Y = CurrentObjectIndex
00EB4E  1               ;
00EB4E  1               ; After:
00EB4E  1               ;   $060F,Y = old $0600,X
00EB4E  1               ;   $0600,X = CurrentObjectIndex
00EB4E  1               ; ----------------------------------------------------------------------------
00EB4E  1               
00EB4E  1               ; ----------------------------------------------------------------------------
00EB4E  1               ; Contract:
00EB4E  1               ;   Description: Updates Object Event Bank  Exchange.
00EB4E  1               ;   Entry: Registers: A, Y; Memory: currentobjectindex, $0600
00EB4E  1               ;   Returns/products: Registers/clobbers: A, Y
00EB4E  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00EB4E  1               ;   Memory effects: $060f, $0600, $069f, $06cf
00EB4E  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00EB4E  1               ;          comparison, load, or store path and are not a stable API product.
00EB4E  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 3.
00EB4E  1               ; ----------------------------------------------------------------------------
00EB4E  1               UpdateObjectEventBank_Exchange: ; $EB4E
00EB4E  1  A4 E1            ldy CurrentObjectIndex      ; $EB4E: A4 E1
00EB50  1               
00EB50  1  BD 00 06         lda $0600,x                 ; $EB50: BD 00 06
00EB53  1  99 0F 06         sta $060F,y                 ; $EB53: 99 0F 06
00EB56  1               
00EB56  1  98               tya                         ; $EB56: 98
00EB57  1  9D 00 06         sta $0600,x                 ; $EB57: 9D 00 06
00EB5A  1               
00EB5A  1               ; ============================================================================
00EB5A  1               ; $EB5A
00EB5A  1               ; Restore two saved event values from the stack.
00EB5A  1               ;
00EB5A  1               ; Entry paths:
00EB5A  1               ;   From $EB46:
00EB5A  1               ;       Y was loaded from CurrentObjectIndex at $EB41.
00EB5A  1               ;
00EB5A  1               ;   From $EB48/$EB4C:
00EB5A  1               ;       Y was reloaded from CurrentObjectIndex at $EB4E.
00EB5A  1               ; ============================================================================
00EB5A  1               
00EB5A  1               UpdateObjectEventBank_Restore:  ; $EB5A
00EB5A  1  18               clc                         ; $EB5A: 18
00EB5B  1                                               ; Establish carry clear for the final BCC.
00EB5B  1               
00EB5B  1               ; ----------------------------------------------------------------------------
00EB5B  1               ; Contract:
00EB5B  1               ;   Description: Internal event-context restoration entry.
00EB5B  1               ;   Entry: Y = object/event index; stack contains two saved context bytes; carry controls final branch.
00EB5B  1               ;   Returns/products: Context arrays restored; stack consumed.
00EB5B  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00EB5B  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00EB5B  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00EB5B  1               ;          comparison, load, or store path and are not a stable API product.
00EB5B  1               ;   Validation: Internal-entry contract; call sites: internal entry.
00EB5B  1               ; ----------------------------------------------------------------------------
00EB5B  1               RestoreObjectEventContext:
00EB5B  1  68               pla                         ; $EB5B: 68
00EB5C  1  99 9F 06         sta $069F,y                 ; $EB5C: 99 9F 06
00EB5F  1               
00EB5F  1  68               pla                         ; $EB5F: 68
00EB60  1  99 CF 06         sta $06CF,y                 ; $EB60: 99 CF 06
00EB63  1               
00EB63  1               ; ----------------------------------------------------------------------------
00EB63  1               ; Transfer to the common exit at $EB6A.
00EB63  1               ;
00EB63  1               ; CLC makes this branch unconditional.
00EB63  1               ; ----------------------------------------------------------------------------
00EB63  1               
00EB63  1  90 05            bcc CommonEngineExit        ; $EB63: 90 05
00EB65  1                                               ; Target $EB6A.
00EB65  1               
00EB65  1               ; ============================================================================
00EB65  1               ; The supplied dump ends at $EB64.
00EB65  1               ;
00EB65  1               ; Leave $EB65 onward untouched until its bytes are verified. The branch above
00EB65  1               ; targets the already-known common engine exit at $EB6A.
00EB65  1               ; ============================================================================
00EB65  1               
00EB65  1               ; ============================================================================
00EB65  1               ; $EB65
00EB65  1               ; Standalone return entry.
00EB65  1               ;
00EB65  1               ; The preceding code at $EB63 branches over this byte to the common exit at
00EB65  1               ; $EB6A. Other callers may use $EB65 as an immediate no-operation return.
00EB65  1               ; ============================================================================
00EB65  1               
00EB65  1               Return_EB65:                    ; $EB65
00EB65  1  60               rts                         ; $EB65: 60
00EB66  1               
00EB66  1               ; ============================================================================
00EB66  1               ; $EB66-$EB9C
00EB66  1               ; Finish the current event, then restore and dispatch the newest queued event.
00EB66  1               ;
00EB66  1               ; Entry:
00EB66  1               ;   Y = object/event index used by the shared stack-restoration path
00EB66  1               ;
00EB66  1               ; Operation:
00EB66  1               ;   1. Enter the stack-restoration path at $EB5B with carry set.
00EB66  1               ;   2. Clear the current object's active-event entry at $06FF,X.
00EB66  1               ;   3. Wait until at least one queued event exists.
00EB66  1               ;   4. Disable NMI while modifying the queue.
00EB66  1               ;   5. Pop the newest queued object index from $0670.
00EB66  1               ;   6. Reset the stack pointer.
00EB66  1               ;   7. Push that object's saved handler/event values.
00EB66  1               ;   8. Return into the queued event's saved continuation.
00EB66  1               ;
00EB66  1               ; This routine implements a stack-based event-context switch.
00EB66  1               ; ============================================================================
00EB66  1               
00EB66  1               ; ----------------------------------------------------------------------------
00EB66  1               ; Contract:
00EB66  1               ;   Description: Implements Dispatch Next Queued Event.
00EB66  1               ;   Entry: Registers: A, X; Memory: currentobjectindex, $e2, $2002, $dd, $0670, $06cf
00EB66  1               ;   Returns/products: Registers/clobbers: A, X, Y
00EB66  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00EB66  1               ;   Memory effects: $06ff, $2000, $e2, currentobjectindex
00EB66  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00EB66  1               ;          comparison, load, or store path and are not a stable API product.
00EB66  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 20.
00EB66  1               ; ----------------------------------------------------------------------------
00EB66  1               DispatchNextQueuedEvent:        ; $EB66
00EB66  1  38               sec                         ; $EB66: 38
00EB67  1               
00EB67  1  20 5B EB         jsr RestoreObjectEventContext                   ; $EB67: 20 5B EB
00EB6A  1                                               ; Enter the previous routine after its CLC.
00EB6A  1                                               ;
00EB6A  1                                               ; Since entry is at $EB5B, carry remains set
00EB6A  1                                               ; through the two PLA/STA operations. Its final
00EB6A  1                                               ; BCC is therefore not taken, allowing this
00EB6A  1                                               ; routine to continue at $EB6A.
00EB6A  1               
00EB6A  1               ; ============================================================================
00EB6A  1               ; $EB6A
00EB6A  1               ; Common continuation used by multiple earlier paths.
00EB6A  1               ; ============================================================================
00EB6A  1               
00EB6A  1               CommonEngineExit:               ; $EB6A
00EB6A  1  A6 E1            ldx CurrentObjectIndex      ; $EB6A: A6 E1
00EB6C  1               
00EB6C  1  A9 00            lda #$00                    ; $EB6C: A9 00
00EB6E  1  9D FF 06         sta $06FF,x                 ; $EB6E: 9D FF 06
00EB71  1                                               ; Mark the current object/event inactive.
00EB71  1               
00EB71  1               ; ----------------------------------------------------------------------------
00EB71  1               ; Check the queued-event count in $E2.
00EB71  1               ; ----------------------------------------------------------------------------
00EB71  1               
00EB71  1  A6 E2            ldx $E2                     ; $EB71: A6 E2
00EB73  1  D0 0C            bne DispatchNextQueuedEvent_HaveEntry
00EB75  1                                               ; $EB73: D0 0C
00EB75  1               
00EB75  1               ; ----------------------------------------------------------------------------
00EB75  1               ; No event is currently queued.
00EB75  1               ;
00EB75  1               ; Read PPUSTATUS to reset the PPU address latch, then restore PPUCTRL from $DD.
00EB75  1               ; Wait until an NMI or another producer adds an event to the queue.
00EB75  1               ; ----------------------------------------------------------------------------
00EB75  1               
00EB75  1  AD 02 20         lda $2002                   ; $EB75: AD 02 20
00EB78  1                                               ; Reset the PPU address latch.
00EB78  1               
00EB78  1  A5 DD            lda PpuCtrlShadow                     ; $EB78: A5 DD
00EB7A  1  8D 00 20         sta $2000                   ; $EB7A: 8D 00 20
00EB7D  1                                               ; Restore the current PPUCTRL value.
00EB7D  1               
00EB7D  1               DispatchNextQueuedEvent_Wait:   ; $EB7D
00EB7D  1  A6 E2            ldx $E2                     ; $EB7D: A6 E2
00EB7F  1  F0 FC            beq DispatchNextQueuedEvent_Wait
00EB81  1                                               ; $EB7F: F0 FC
00EB81  1               
00EB81  1               ; ----------------------------------------------------------------------------
00EB81  1               ; At least one queued event exists.
00EB81  1               ;
00EB81  1               ; Disable NMI by clearing bit seven of the saved PPUCTRL value.
00EB81  1               ; ----------------------------------------------------------------------------
00EB81  1               
00EB81  1               DispatchNextQueuedEvent_HaveEntry: ; $EB81
00EB81  1  A5 DD            lda PpuCtrlShadow                     ; $EB81: A5 DD
00EB83  1  29 7F            and #$7F                    ; $EB83: 29 7F
00EB85  1  8D 00 20         sta $2000                   ; $EB85: 8D 00 20
00EB88  1               
00EB88  1               ; ----------------------------------------------------------------------------
00EB88  1               ; Remove the newest object/event index from the queue.
00EB88  1               ;
00EB88  1               ; $E2 behaves as a count/next-free index:
00EB88  1               ;
00EB88  1               ;   X = $E2 - 1
00EB88  1               ;   CurrentObjectIndex = $0670,X
00EB88  1               ;   $E2 = X
00EB88  1               ; ----------------------------------------------------------------------------
00EB88  1               
00EB88  1  CA               dex                         ; $EB88: CA
00EB89  1  86 E2            stx $E2                     ; $EB89: 86 E2
00EB8B  1               
00EB8B  1  BD 70 06         lda $0670,x                 ; $EB8B: BD 70 06
00EB8E  1  85 E1            sta CurrentObjectIndex      ; $EB8E: 85 E1
00EB90  1  A8               tay                         ; $EB90: A8
00EB91  1                                               ; Y = queued object/event index.
00EB91  1               
00EB91  1               ; ----------------------------------------------------------------------------
00EB91  1               ; Reset the hardware stack.
00EB91  1               ;
00EB91  1               ; Setting SP to $FF discards the current call chain. The saved event values
00EB91  1               ; pushed below become the return context used by RTS.
00EB91  1               ; ----------------------------------------------------------------------------
00EB91  1               
00EB91  1  A2 FF            ldx #$FF                    ; $EB91: A2 FF
00EB93  1  9A               txs                         ; $EB93: 9A
00EB94  1               
00EB94  1               ; ----------------------------------------------------------------------------
00EB94  1               ; Push the queued object's saved continuation/context bytes.
00EB94  1               ;
00EB94  1               ; RTS at $EB9C pulls these bytes as its return address. The low byte is pushed
00EB94  1               ; second because RTS pulls low byte first.
00EB94  1               ; ----------------------------------------------------------------------------
00EB94  1               
00EB94  1  B9 CF 06         lda $06CF,y                 ; $EB94: B9 CF 06
00EB97  1  48               pha                         ; $EB97: 48
00EB98  1                                               ; Push saved high byte.
00EB98  1               
00EB98  1  B9 9F 06         lda $069F,y                 ; $EB98: B9 9F 06
00EB9B  1  48               pha                         ; $EB9B: 48
00EB9C  1                                               ; Push saved low byte.
00EB9C  1               
00EB9C  1  60               rts                         ; $EB9C: 60
00EB9D  1                                               ; Resume the queued event continuation.
00EB9D  1               
00EB9D  1               ; ============================================================================
00EB9D  1               ; $EB9D-$EBB3
00EB9D  1               ; Initialize the queued-event system and clear its event arrays.
00EB9D  1               ;
00EB9D  1               ; Operation:
00EB9D  1               ;   1. Clear the full $0600-$06FF page.
00EB9D  1               ;   2. Clear the queue count at $E2.
00EB9D  1               ;   3. Set CurrentObjectIndex to $01.
00EB9D  1               ;   4. Clear $30 entries in the active-event array beginning at $06FF.
00EB9D  1               ;
00EB9D  1               ; Exit:
00EB9D  1               ;   A = $00
00EB9D  1               ;   X = $00
00EB9D  1               ;   $E2 = $00
00EB9D  1               ;   CurrentObjectIndex = $01
00EB9D  1               ; ============================================================================
00EB9D  1               
00EB9D  1               ; ----------------------------------------------------------------------------
00EB9D  1               ; Contract:
00EB9D  1               ;   Description: Initializes Queued Event System.
00EB9D  1               ;   Entry: Registers: A, X
00EB9D  1               ;   Returns/products: Registers/clobbers: A, X
00EB9D  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00EB9D  1               ;   Memory effects: $0600, $e2, currentobjectindex, $06ff
00EB9D  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00EB9D  1               ;          comparison, load, or store path and are not a stable API product.
00EB9D  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 4.
00EB9D  1               ; ----------------------------------------------------------------------------
00EB9D  1               InitializeQueuedEventSystem:    ; $EB9D
00EB9D  1  A9 00            lda #$00                    ; $EB9D: A9 00
00EB9F  1  AA               tax                         ; $EB9F: AA
00EBA0  1                                               ; A = $00, X = $00.
00EBA0  1               
00EBA0  1               ; ----------------------------------------------------------------------------
00EBA0  1               ; Clear the full $0600-$06FF page.
00EBA0  1               ;
00EBA0  1               ; X begins at zero and wraps after 256 iterations:
00EBA0  1               ;
00EBA0  1               ;   $0600,X = $00
00EBA0  1               ;   ...
00EBA0  1               ;   $06FF,X = $00
00EBA0  1               ; ----------------------------------------------------------------------------
00EBA0  1               
00EBA0  1               InitializeQueuedEventSystem_ClearPage: ; $EBA0
00EBA0  1  9D 00 06         sta $0600,x                 ; $EBA0: 9D 00 06
00EBA3  1               
00EBA3  1  E8               inx                         ; $EBA3: E8
00EBA4  1  D0 FA            bne InitializeQueuedEventSystem_ClearPage
00EBA6  1                                               ; $EBA4: D0 FA
00EBA6  1               
00EBA6  1               ; ----------------------------------------------------------------------------
00EBA6  1               ; Clear the queued-event count or next-free queue index.
00EBA6  1               ; ----------------------------------------------------------------------------
00EBA6  1               
00EBA6  1  85 E2            sta $E2                     ; $EBA6: 85 E2
00EBA8  1               
00EBA8  1               ; ----------------------------------------------------------------------------
00EBA8  1               ; X wrapped to zero after the page clear. Increment it to one and use that as
00EBA8  1               ; the initial current-object/event index.
00EBA8  1               ; ----------------------------------------------------------------------------
00EBA8  1               
00EBA8  1  E8               inx                         ; $EBA8: E8
00EBA9  1                                               ; X = $01.
00EBA9  1               
00EBA9  1  86 E1            stx CurrentObjectIndex      ; $EBA9: 86 E1
00EBAB  1               
00EBAB  1               ; ----------------------------------------------------------------------------
00EBAB  1               ; Clear the active-event entries $06FF-$072E.
00EBAB  1               ;
00EBAB  1               ; X begins at $30. Because the indexed base is $06FF, the effective addresses
00EBAB  1               ; are:
00EBAB  1               ;
00EBAB  1               ;   X=$30 -> $072F
00EBAB  1               ;   ...
00EBAB  1               ;   X=$01 -> $0700
00EBAB  1               ;
00EBAB  1               ; The loop does not write with X=$00.
00EBAB  1               ;
00EBAB  1               ; Note that $06FF itself was already cleared by the full-page loop above.
00EBAB  1               ; ----------------------------------------------------------------------------
00EBAB  1               
00EBAB  1  A2 30            ldx #$30                    ; $EBAB: A2 30
00EBAD  1               
00EBAD  1               InitializeQueuedEventSystem_ClearActive: ; $EBAD
00EBAD  1  9D FF 06         sta $06FF,x                 ; $EBAD: 9D FF 06
00EBB0  1               
00EBB0  1  CA               dex                         ; $EBB0: CA
00EBB1  1  D0 FA            bne InitializeQueuedEventSystem_ClearActive
00EBB3  1                                               ; $EBB1: D0 FA
00EBB3  1               
00EBB3  1  60               rts                         ; $EBB3: 60
00EBB4  1               
00EBB4  1               ; ============================================================================
00EBB4  1               ; $EBB4-$EBBB
00EBB4  1               ; Convert A into a three-bit value relative to $E3, then enter the common
00EBB4  1               ; object-event bank routine at $EB41.
00EBB4  1               ;
00EBB4  1               ; Entry:
00EBB4  1               ;   A = source value
00EBB4  1               ;
00EBB4  1               ; Calculation:
00EBB4  1               ;   A = (A - $E3) & $07
00EBB4  1               ; ============================================================================
00EBB4  1               
00EBB4  1               UpdateRelativeObjectEventBank:  ; $EBB4
00EBB4  1  38               sec                         ; $EBB4: 38
00EBB5  1               
00EBB5  1  E5 E3            sbc FrameCounter                     ; $EBB5: E5 E3
00EBB7  1               
00EBB7  1  29 07            and #$07                    ; $EBB7: 29 07
00EBB9  1               
00EBB9  1  4C 41 EB         jmp StoreObjectEventBankValue                   ; $EBB9: 4C 41 EB
00EBBC  1               
00EBBC  1               ; ============================================================================
00EBBC  1               ; $EBBC-$EBDB
00EBBC  1               ; Structured rendering or animation data.
00EBBC  1               ;
00EBBC  1               ; This region does not begin with a plausible executable entry point:
00EBBC  1               ;
00EBBC  1               ;   $EBBC: D6 E1
00EBBC  1               ;   $EBBE: B1 C7
00EBBC  1               ;   $EBC0: BE C2
00EBBC  1               ;
00EBBC  1               ; The following bytes contain repeating values and fields resembling sprite or
00EBBC  1               ; animation records. Keep the exact byte layout until the routines that index
00EBBC  1               ; this region reveal its record boundaries.
00EBBC  1               ; ============================================================================
00EBBC  1               
00EBBC  1               RenderingData_EBBC:             ; $EBBC
00EBBC  1  D6 E1 B1 C7      .byte $D6,$E1,$B1,$C7,$BE,$C2,$50,$03
00EBC0  1  BE C2 50 03  
00EBC4  1  00 27 50 03      .byte $00,$27,$50,$03,$00,$1F,$A8,$02
00EBC8  1  00 1F A8 02  
00EBCC  1  3F 27 A8 02      .byte $3F,$27,$A8,$02,$3F,$1F,$A4,$03
00EBD0  1  3F 1F A4 03  
00EBD4  1  F3 17 05 F0      .byte $F3,$17,$05,$F0,$C8,$41,$04,$E0
00EBD8  1  C8 41 04 E0  
00EBDC  1               
00EBDC  1               ; ============================================================================
00EBDC  1               ; $EBDC-$EBFB
00EBDC  1               ; Structured rendering or animation data, continued.
00EBDC  1               ;
00EBDC  1               ; The repeating $41 values and surrounding control-like fields suggest compact
00EBDC  1               ; rendering records, but the record boundaries remain unverified. Preserve the
00EBDC  1               ; exact raw byte layout.
00EBDC  1               ; ============================================================================
00EBDC  1               
00EBDC  1               RenderingData_EBDC:             ; $EBDC
00EBDC  1  C9 41 FC E8      .byte $C9,$41,$FC,$E8,$CA,$41,$FC,$F0
00EBE0  1  CA 41 FC F0  
00EBE4  1  CB 41 FC F8      .byte $CB,$41,$FC,$F8,$CC,$41,$FC,$04
00EBE8  1  CC 41 FC 04  
00EBEC  1  F0 CD 41 04      .byte $F0,$CD,$41,$04,$E8,$CE,$41,$FC
00EBF0  1  E8 CE 41 FC  
00EBF4  1  F0 CF 41 FC      .byte $F0,$CF,$41,$FC,$F8,$D0,$41,$FC
00EBF8  1  F8 D0 41 FC  
00EBFC  1               
00EBFC  1               ; ============================================================================
00EBFC  1               ; $EBFC-$EC1B
00EBFC  1               ; Structured rendering or animation data, continued.
00EBFC  1               ;
00EBFC  1               ; This block retains the same compact record pattern seen in the preceding
00EBFC  1               ; region. Preserve the raw bytes until the consuming renderer reveals the
00EBFC  1               ; exact record boundaries and field meanings.
00EBFC  1               ; ============================================================================
00EBFC  1               
00EBFC  1               RenderingData_EBFC:             ; $EBFC
00EBFC  1  05 E8 D1 41      .byte $05,$E8,$D1,$41,$FC,$F0,$D2,$41
00EC00  1  FC F0 D2 41  
00EC04  1  FC F8 D3 41      .byte $FC,$F8,$D3,$41,$FC,$F0,$D4,$41
00EC08  1  FC F0 D4 41  
00EC0C  1  F4 F6 D5 41      .byte $F4,$F6,$D5,$41,$EC,$05,$E8,$D7
00EC10  1  EC 05 E8 D7  
00EC14  1  41 FC F0 D8      .byte $41,$FC,$F0,$D8,$41,$FC,$F8,$D9
00EC18  1  41 FC F8 D9  
00EC1C  1               
00EC1C  1               ; ============================================================================
00EC1C  1               ; Resume untouched PRG-ROM at file offset $2C1C.
00EC1C  1               ;
00EC1C  1               ; CPU data range: $EBFC-$EC1B
00EC1C  1               ; ROM data range: $2BFC-$2C1B
00EC1C  1               ; Length decoded: $0020 bytes
00EC1C  1               ;
00EC1C  1               ; $4000 - $2C1C = $13E4 bytes remaining.
00EC1C  1               ;
00EC1C  1               ; The structured data continues at CPU $EC1C.
00EC1C  1               ; ============================================================================
00EC1C  1               ; $EC1C-$F9CF
00EC1C  1               ; Structured rendering, animation, sprite, text, and lookup data.
00EC1C  1               ;
00EC1C  1               ; This continues the record data beginning at $EBBC. The region contains many
00EC1C  1               ; repeating compact record formats, including:
00EC1C  1               ;
00EC1C  1               ;   - animation frame descriptions
00EC1C  1               ;   - sprite coordinate and attribute records
00EC1C  1               ;   - display and text data
00EC1C  1               ;   - pointer and lookup tables
00EC1C  1               ;   - unused $FF padding near the end
00EC1C  1               ;
00EC1C  1               ; No reliable executable entry point occurs inside this range. Preserve the
00EC1C  1               ; bytes directly until all consuming routines and record formats are mapped.
00EC1C  1               ;
00EC1C  1               ; CPU range:
00EC1C  1               ;   $EC1C-$F9CF
00EC1C  1               ;
00EC1C  1               ; ROM range:
00EC1C  1               ;   $2C1C-$39CF
00EC1C  1               ;
00EC1C  1               ; Length:
00EC1C  1               ;   $39D0 - $2C1C = $0DB4 bytes
00EC1C  1               ; ============================================================================
00EC1C  1               
00EC1C  1               RenderingAndAnimationData_EC1C:
00EC1C  1                   ; ============================================================================
00EC1C  1               ; $EC1C-$F9CF
00EC1C  1               ; Structured rendering, animation, sprite, text, and lookup data.
00EC1C  1               ;
00EC1C  1               ; This region has no executable entry points. The only confirmed direct code
00EC1C  1               ; reference is FrameOamTemplate_F94D, copied as 88 bytes into OAM shadow RAM
00EC1C  1               ; by CopyTransitionOamTemplate at $C2E6.
00EC1C  1               ;
00EC1C  1               ; Record boundaries outside the confirmed OAM template remain provisional, so
00EC1C  1               ; the bytes are preserved explicitly without assigning unsupported semantics.
00EC1C  1               ; ============================================================================
00EC1C  1               
00EC1C  1                   ; Explicit bytes begin at CPU $EC1C.
00EC1C  1  41 FC F0 DA      .byte $41,$FC,$F0,$DA,$41,$F4,$F0,$DB,$41,$EC,$05,$E8,$DC,$41,$FC,$F0   ; $EC1C
00EC20  1  41 F4 F0 DB  
00EC24  1  41 EC 05 E8  
00EC2C  1  DD 41 FC F8      .byte $DD,$41,$FC,$F8,$DE,$41,$FC,$E8,$DF,$41,$F4,$E5,$E0,$41,$EC,$05   ; $EC2C
00EC30  1  DE 41 FC E8  
00EC34  1  DF 41 F4 E5  
00EC3C  1  E8 E2 41 04      .byte $E8,$E2,$41,$04,$F0,$E3,$41,$04,$E8,$E4,$41,$FC,$F0,$DD,$41,$FC   ; $EC3C
00EC40  1  F0 E3 41 04  
00EC44  1  E8 E4 41 FC  
00EC4C  1  F8 DE 41 FC      .byte $F8,$DE,$41,$FC,$00,$05,$E8,$A5,$40,$00,$F0,$A0,$40,$00,$F8,$A1   ; $EC4C
00EC50  1  00 05 E8 A5  
00EC54  1  40 00 F0 A0  
00EC5C  1  40 FB E8 A6      .byte $40,$FB,$E8,$A6,$40,$F8,$F0,$A3,$40,$F8,$04,$E8,$9F,$40,$FC,$F0   ; $EC5C
00EC60  1  40 F8 F0 A3  
00EC64  1  40 F8 04 E8  
00EC6C  1  A0 40 00 F8      .byte $A0,$40,$00,$F8,$A1,$40,$FB,$F0,$A3,$40,$F8,$05,$E8,$A7,$40,$00   ; $EC6C
00EC70  1  A1 40 FB F0  
00EC74  1  A3 40 F8 05  
00EC7C  1  F0 A8 40 00      .byte $F0,$A8,$40,$00,$F8,$A9,$40,$FA,$E8,$AA,$40,$F8,$F0,$AB,$40,$F8   ; $EC7C
00EC80  1  F8 A9 40 FA  
00EC84  1  E8 AA 40 F8  
00EC8C  1  05 E8 AD 40      .byte $05,$E8,$AD,$40,$00,$F0,$A8,$40,$00,$F8,$A9,$40,$FA,$E8,$AE,$40   ; $EC8C
00EC90  1  00 F0 A8 40  
00EC94  1  00 F8 A9 40  
00EC9C  1  F8 F0 AB 40      .byte $F8,$F0,$AB,$40,$F8,$05,$F3,$C1,$40,$04,$E8,$C3,$40,$FC,$F0,$C4   ; $EC9C
00ECA0  1  F8 05 F3 C1  
00ECA4  1  40 04 E8 C3  
00ECAC  1  40 FC F8 C5      .byte $40,$FC,$F8,$C5,$40,$FC,$EB,$C6,$40,$F4,$05,$EC,$93,$40,$04,$E8   ; $ECAC
00ECB0  1  40 FC EB C6  
00ECB4  1  40 F4 05 EC  
00ECBC  1  C3 00 FC F0      .byte $C3,$00,$FC,$F0,$94,$40,$FC,$F8,$C5,$00,$FC,$F3,$C1,$00,$F4,$06   ; $ECBC
00ECC0  1  94 40 FC F8  
00ECC4  1  C5 00 FC F3  
00ECCC  1  EC AF 40 04      .byte $EC,$AF,$40,$04,$F8,$B0,$40,$04,$EC,$B2,$40,$FC,$F4,$B3,$40,$FC   ; $ECCC
00ECD0  1  F8 B0 40 04  
00ECD4  1  EC B2 40 FC  
00ECDC  1  FC B4 40 FC      .byte $FC,$B4,$40,$FC,$F4,$B5,$40,$F4,$06,$EC,$AF,$40,$04,$F4,$B6,$40   ; $ECDC
00ECE0  1  F4 B5 40 F4  
00ECE4  1  06 EC AF 40  
00ECEC  1  04 EC B2 40      .byte $04,$EC,$B2,$40,$FC,$F4,$B3,$40,$FC,$FC,$B4,$40,$FC,$F4,$B5,$40   ; $ECEC
00ECF0  1  FC F4 B3 40  
00ECF4  1  FC FC B4 40  
00ECFC  1  F4 04 EC B7      .byte $F4,$04,$EC,$B7   ; $ECFC
00ED00  1               
00ED00  1               RenderingAnimationData_ED00:          ; $ED00
00ED00  1  40 04 EC B8      .byte $40,$04,$EC,$B8,$40,$FC,$F4,$B9,$40,$FC,$FC,$BA,$40,$FC,$05,$F0   ; $ED00
00ED04  1  40 FC F4 B9  
00ED08  1  40 FC FC BA  
00ED10  1  BB 40 FC F8      .byte $BB,$40,$FC,$F8,$BC,$40,$00,$00,$BD,$40,$00,$F8,$BF,$40,$F8,$00   ; $ED10
00ED14  1  BC 40 00 00  
00ED18  1  BD 40 00 F8  
00ED20  1  C0 40 F8 05      .byte $C0,$40,$F8,$05,$E8,$E7,$40,$00,$F0,$E8,$40,$00,$F8,$A9,$40,$FA   ; $ED20
00ED24  1  E8 E7 40 00  
00ED28  1  F0 E8 40 00  
00ED30  1  E8 AA 40 F8      .byte $E8,$AA,$40,$F8,$F0,$E9,$40,$F8,$00,$05,$F0,$C8,$01,$F4,$E0,$C9   ; $ED30
00ED34  1  F0 E9 40 F8  
00ED38  1  00 05 F0 C8  
00ED40  1  01 FC E8 CA      .byte $01,$FC,$E8,$CA,$01,$FC,$F0,$CB,$01,$FC,$F8,$CC,$01,$FC,$04,$F0   ; $ED40
00ED44  1  01 FC F0 CB  
00ED48  1  01 FC F8 CC  
00ED50  1  CD 01 F4 E8      .byte $CD,$01,$F4,$E8,$CE,$01,$FC,$F0,$CF,$01,$FC,$F8,$D0,$01,$FC,$05   ; $ED50
00ED54  1  CE 01 FC F0  
00ED58  1  CF 01 FC F8  
00ED60  1  E8 D1 01 FC      .byte $E8,$D1,$01,$FC,$F0,$D2,$01,$FC,$F8,$D3,$01,$FC,$F0,$D4,$01,$04   ; $ED60
00ED64  1  F0 D2 01 FC  
00ED68  1  F8 D3 01 FC  
00ED70  1  F6 D5 01 0C      .byte $F6,$D5,$01,$0C,$05,$E8,$D7,$01,$FC,$F0,$D8,$01,$FC,$F8,$D9,$01   ; $ED70
00ED74  1  05 E8 D7 01  
00ED78  1  FC F0 D8 01  
00ED80  1  FC F0 DA 01      .byte $FC,$F0,$DA,$01,$04,$F0,$DB,$01,$0C,$05,$E8,$DC,$01,$FC,$F0,$DD   ; $ED80
00ED84  1  04 F0 DB 01  
00ED88  1  0C 05 E8 DC  
00ED90  1  01 FC F8 DE      .byte $01,$FC,$F8,$DE,$01,$FC,$E8,$DF,$01,$04,$E5,$E0,$01,$0C,$05,$E8   ; $ED90
00ED94  1  01 FC E8 DF  
00ED98  1  01 04 E5 E0  
00EDA0  1  E2 01 F4 F0      .byte $E2,$01,$F4,$F0,$E3,$01,$F4,$E8,$E4,$01,$FC,$F0,$DD,$01,$FC,$F8   ; $EDA0
00EDA4  1  E3 01 F4 E8  
00EDA8  1  E4 01 FC F0  
00EDB0  1  DE 01 FC 00      .byte $DE,$01,$FC,$00,$05,$E8,$A5,$00,$F8,$F0,$A0,$00,$F8,$F8,$A1,$00   ; $EDB0
00EDB4  1  05 E8 A5 00  
00EDB8  1  F8 F0 A0 00  
00EDC0  1  FD E8 A6 00      .byte $FD,$E8,$A6,$00,$00,$F0,$A3,$00,$00,$04,$E8,$9F,$00,$FC,$F0,$A0   ; $EDC0
00EDC4  1  00 F0 A3 00  
00EDC8  1  00 04 E8 9F  
00EDD0  1  00 F8 F8 A1      .byte $00,$F8,$F8,$A1,$00,$FD,$F0,$A3,$00,$00,$05,$E8,$A7,$00,$F8,$F0   ; $EDD0
00EDD4  1  00 FD F0 A3  
00EDD8  1  00 00 05 E8  
00EDE0  1  A8 00 F8 F8      .byte $A8,$00,$F8,$F8,$A9,$00,$FE,$E8,$AA,$00,$00,$F0,$AB,$00,$00,$05   ; $EDE0
00EDE4  1  A9 00 FE E8  
00EDE8  1  AA 00 00 F0  
00EDF0  1  E8 AD 00 F8      .byte $E8,$AD,$00,$F8,$F0,$A8,$00,$F8,$F8,$A9,$00,$FE,$E8,$AE,$00,$00   ; $EDF0
00EDF4  1  F0 A8 00 F8  
00EDF8  1  F8 A9 00 FE  
00EE00  1               
00EE00  1               RenderingAnimationData_EE00:          ; $EE00
00EE00  1  F0 AB 00 00      .byte $F0,$AB,$00,$00,$05,$EC,$93,$00,$EC,$E8,$C3,$40,$F4,$F0,$94,$00   ; $EE00
00EE04  1  05 EC 93 00  
00EE08  1  EC E8 C3 40  
00EE10  1  F4 F8 C5 40      .byte $F4,$F8,$C5,$40,$F4,$F3,$C1,$40,$FC,$05,$F1,$C1,$00,$F4,$E6,$C3   ; $EE10
00EE14  1  F4 F3 C1 40  
00EE18  1  FC 05 F1 C1  
00EE20  1  00 FC EE C4      .byte $00,$FC,$EE,$C4,$00,$FC,$F6,$C5,$00,$FC,$E9,$C6,$00,$04,$06,$EC   ; $EE20
00EE24  1  00 FC F6 C5  
00EE28  1  00 FC E9 C6  
00EE30  1  AF 00 F4 F8      .byte $AF,$00,$F4,$F8,$B0,$00,$F4,$EC,$B2,$00,$FC,$F4,$B3,$00,$FC,$FC   ; $EE30
00EE34  1  B0 00 F4 EC  
00EE38  1  B2 00 FC F4  
00EE40  1  B4 00 FC F4      .byte $B4,$00,$FC,$F4,$B5,$00,$04,$06,$EC,$AF,$00,$F4,$F4,$B6,$00,$F4   ; $EE40
00EE44  1  B5 00 04 06  
00EE48  1  EC AF 00 F4  
00EE50  1  EC B2 00 FC      .byte $EC,$B2,$00,$FC,$F4,$B3,$00,$FC,$FC,$B4,$00,$FC,$F4,$B5,$00,$04   ; $EE50
00EE54  1  F4 B3 00 FC  
00EE58  1  FC B4 00 FC  
00EE60  1  04 EC B7 00      .byte $04,$EC,$B7,$00,$F4,$EC,$B8,$00,$FC,$F4,$B9,$00,$FC,$FC,$BA,$00   ; $EE60
00EE64  1  F4 EC B8 00  
00EE68  1  FC F4 B9 00  
00EE70  1  FC 05 F0 BB      .byte $FC,$05,$F0,$BB,$00,$FC,$F8,$BC,$00,$F8,$00,$BD,$00,$F8,$F8,$BF   ; $EE70
00EE74  1  00 FC F8 BC  
00EE78  1  00 F8 00 BD  
00EE80  1  00 00 00 C0      .byte $00,$00,$00,$C0,$00,$00,$05,$E8,$E7,$00,$F8,$F0,$E8,$00,$F8,$F8   ; $EE80
00EE84  1  00 00 05 E8  
00EE88  1  E7 00 F8 F0  
00EE90  1  A9 00 FE E8      .byte $A9,$00,$FE,$E8,$AA,$00,$00,$F0,$E9,$00,$00,$00,$04,$F0,$68,$40   ; $EE90
00EE94  1  AA 00 00 F0  
00EE98  1  E9 00 00 00  
00EEA0  1  F8 F8 69 40      .byte $F8,$F8,$69,$40,$F8,$F0,$68,$00,$00,$F8,$69,$00,$00,$06,$E8,$6A   ; $EEA0
00EEA4  1  F8 F0 68 00  
00EEA8  1  00 F8 69 00  
00EEB0  1  40 F8 F0 6B      .byte $40,$F8,$F0,$6B,$40,$F8,$F8,$6C,$40,$F8,$E8,$6D,$00,$00,$F0,$6E   ; $EEB0
00EEB4  1  40 F8 F8 6C  
00EEB8  1  40 F8 E8 6D  
00EEC0  1  00 00 F8 6F      .byte $00,$00,$F8,$6F,$00,$00,$06,$E8,$6A,$40,$F8,$F0,$6B,$40,$F8,$F8   ; $EEC0
00EEC4  1  00 00 06 E8  
00EEC8  1  6A 40 F8 F0  
00EED0  1  6C 40 F8 E8      .byte $6C,$40,$F8,$E8,$6A,$00,$00,$F0,$6B,$00,$00,$F8,$6C,$00,$00,$05   ; $EED0
00EED4  1  6A 00 00 F0  
00EED8  1  6B 00 00 F8  
00EEE0  1  F1 97 00 F8      .byte $F1,$97,$00,$F8,$F9,$7E,$00,$F8,$E9,$98,$00,$FE,$F1,$10,$00,$00   ; $EEE0
00EEE4  1  F9 7E 00 F8  
00EEE8  1  E9 98 00 FE  
00EEF0  1  F9 81 00 00      .byte $F9,$81,$00,$00,$05,$F0,$11,$00,$F8,$F8,$83,$00,$F8,$E8,$98,$00   ; $EEF0
00EEF4  1  05 F0 11 00  
00EEF8  1  F8 F8 83 00  
00EF00  1               
00EF00  1               RenderingAnimationData_EF00:          ; $EF00
00EF00  1  FE F0 12 00      .byte $FE,$F0,$12,$00,$00,$F8,$8E,$00,$00,$05,$F0,$13,$00,$F8,$F8,$90   ; $EF00
00EF04  1  00 F8 8E 00  
00EF08  1  00 05 F0 13  
00EF10  1  00 F8 E8 98      .byte $00,$F8,$E8,$98,$00,$FE,$F0,$14,$00,$00,$F8,$92,$00,$00,$05,$F1   ; $EF10
00EF14  1  00 FE F0 14  
00EF18  1  00 00 F8 92  
00EF20  1  97 40 00 F9      .byte $97,$40,$00,$F9,$7E,$40,$00,$E9,$98,$40,$FA,$F1,$10,$40,$F8,$F9   ; $EF20
00EF24  1  7E 40 00 E9  
00EF28  1  98 40 FA F1  
00EF30  1  81 40 F8 05      .byte $81,$40,$F8,$05,$F0,$11,$40,$00,$F8,$83,$40,$00,$E8,$98,$40,$FA   ; $EF30
00EF34  1  F0 11 40 00  
00EF38  1  F8 83 40 00  
00EF40  1  F0 12 40 F8      .byte $F0,$12,$40,$F8,$F8,$8E,$40,$F8,$05,$F0,$13,$40,$00,$F8,$90,$40   ; $EF40
00EF44  1  F8 8E 40 F8  
00EF48  1  05 F0 13 40  
00EF50  1  00 E8 98 40      .byte $00,$E8,$98,$40,$FA,$F0,$14,$40,$F8,$F8,$92,$40,$F8,$05,$F1,$7D   ; $EF50
00EF54  1  FA F0 14 40  
00EF58  1  F8 F8 92 40  
00EF60  1  01 F8 F9 7E      .byte $01,$F8,$F9,$7E,$01,$F8,$E9,$7F,$01,$00,$F1,$80,$01,$00,$F9,$81   ; $EF60
00EF64  1  01 F8 E9 7F  
00EF68  1  01 00 F1 80  
00EF70  1  01 00 05 F0      .byte $01,$00,$05,$F0,$82,$01,$F8,$F8,$83,$01,$F8,$E8,$7F,$01,$00,$F0   ; $EF70
00EF74  1  82 01 F8 F8  
00EF78  1  83 01 F8 E8  
00EF80  1  8D 01 00 F8      .byte $8D,$01,$00,$F8,$8E,$01,$00,$05,$F0,$8F,$01,$F8,$F8,$90,$01,$F8   ; $EF80
00EF84  1  8E 01 00 05  
00EF88  1  F0 8F 01 F8  
00EF90  1  E8 7F 01 00      .byte $E8,$7F,$01,$00,$F0,$91,$01,$00,$F8,$92,$01,$00,$04,$F0,$89,$01   ; $EF90
00EF94  1  F0 91 01 00  
00EF98  1  F8 92 01 00  
00EFA0  1  F8 F8 8A 01      .byte $F8,$F8,$8A,$01,$F8,$F0,$8B,$01,$00,$F8,$8C,$01,$00,$05,$F1,$7D   ; $EFA0
00EFA4  1  F8 F0 8B 01  
00EFA8  1  00 F8 8C 01  
00EFB0  1  41 00 F9 7E      .byte $41,$00,$F9,$7E,$41,$00,$E9,$7F,$41,$F8,$F1,$80,$41,$F8,$F9,$81   ; $EFB0
00EFB4  1  41 00 E9 7F  
00EFB8  1  41 F8 F1 80  
00EFC0  1  41 F8 05 F0      .byte $41,$F8,$05,$F0,$82,$41,$00,$F8,$83,$41,$00,$E8,$7F,$41,$F8,$F0   ; $EFC0
00EFC4  1  82 41 00 F8  
00EFC8  1  83 41 00 E8  
00EFD0  1  8D 41 F8 F8      .byte $8D,$41,$F8,$F8,$8E,$41,$F8,$05,$F0,$8F,$41,$00,$F8,$90,$41,$00   ; $EFD0
00EFD4  1  8E 41 F8 05  
00EFD8  1  F0 8F 41 00  
00EFE0  1  E8 7F 41 F8      .byte $E8,$7F,$41,$F8,$F0,$91,$41,$F8,$F8,$92,$41,$F8,$05,$F8,$99,$01   ; $EFE0
00EFE4  1  F0 91 41 F8  
00EFE8  1  F8 92 41 F8  
00EFF0  1  F4 F8 9A 01      .byte $F4,$F8,$9A,$01,$FC,$F0,$9B,$01,$04,$F8,$9C,$01,$04,$F8,$9D,$03   ; $EFF0
00EFF4  1  FC F0 9B 01  
00EFF8  1  04 F8 9C 01  
00F000  1               
00F000  1               RenderingAnimationData_F000:          ; $F000
00F000  1  0C 05 F8 99      .byte $0C,$05,$F8,$99,$01,$F4,$F8,$9A,$01,$FC,$F0,$9B,$01,$04,$F8,$9C   ; $F000
00F004  1  01 F4 F8 9A  
00F008  1  01 FC F0 9B  
00F010  1  01 04 F8 9E      .byte $01,$04,$F8,$9E,$03,$14,$05,$F0,$70,$41,$00,$F8,$71,$41,$00,$E8   ; $F010
00F014  1  03 14 05 F0  
00F018  1  70 41 00 F8  
00F020  1  72 41 F8 F0      .byte $72,$41,$F8,$F0,$73,$41,$F8,$F8,$74,$41,$F8,$05,$F0,$75,$41,$00   ; $F020
00F024  1  73 41 F8 F8  
00F028  1  74 41 F8 05  
00F030  1  F8 76 41 00      .byte $F8,$76,$41,$00,$E8,$72,$41,$F8,$F0,$77,$41,$F8,$F8,$78,$41,$F8   ; $F030
00F034  1  E8 72 41 F8  
00F038  1  F0 77 41 F8  
00F040  1  05 F1 79 41      .byte $05,$F1,$79,$41,$00,$F9,$7A,$41,$00,$E9,$72,$41,$F8,$F1,$7B,$41   ; $F040
00F044  1  00 F9 7A 41  
00F048  1  00 E9 72 41  
00F050  1  F8 F9 7C 41      .byte $F8,$F9,$7C,$41,$F8,$05,$E8,$84,$01,$F8,$F0,$85,$01,$F8,$F8,$86   ; $F050
00F054  1  F8 05 E8 84  
00F058  1  01 F8 F0 85  
00F060  1  01 F8 F0 87      .byte $01,$F8,$F0,$87,$01,$00,$F8,$88,$01,$00,$05,$F0,$70,$01,$F8,$F8   ; $F060
00F064  1  01 00 F8 88  
00F068  1  01 00 05 F0  
00F070  1  71 01 F8 E8      .byte $71,$01,$F8,$E8,$72,$01,$00,$F0,$73,$01,$00,$F8,$74,$01,$00,$05   ; $F070
00F074  1  72 01 00 F0  
00F078  1  73 01 00 F8  
00F080  1  F0 75 01 F8      .byte $F0,$75,$01,$F8,$F8,$76,$01,$F8,$E8,$72,$01,$00,$F0,$77,$01,$00   ; $F080
00F084  1  F8 76 01 F8  
00F088  1  E8 72 01 00  
00F090  1  F8 78 01 00      .byte $F8,$78,$01,$00,$05,$F1,$79,$01,$F8,$F9,$7A,$01,$F8,$E9,$72,$01   ; $F090
00F094  1  05 F1 79 01  
00F098  1  F8 F9 7A 01  
00F0A0  1  00 F1 7B 01      .byte $00,$F1,$7B,$01,$00,$F9,$7C,$01,$00,$04,$F0,$5B,$00,$F8,$F8,$5C   ; $F0A0
00F0A4  1  00 F9 7C 01  
00F0A8  1  00 04 F0 5B  
00F0B0  1  00 F8 F0 5D      .byte $00,$F8,$F0,$5D,$00,$00,$F8,$5E,$00,$00,$04,$F0,$5B,$40,$00,$F8   ; $F0B0
00F0B4  1  00 00 F8 5E  
00F0B8  1  00 00 04 F0  
00F0C0  1  5C 40 00 F0      .byte $5C,$40,$00,$F0,$5D,$40,$F8,$F8,$5E,$40,$F8,$04,$F0,$5F,$00,$F8   ; $F0C0
00F0C4  1  5D 40 F8 F8  
00F0C8  1  5E 40 F8 04  
00F0D0  1  F8 60 00 F8      .byte $F8,$60,$00,$F8,$F0,$61,$00,$00,$F8,$62,$00,$00,$05,$F0,$63,$00   ; $F0D0
00F0D4  1  F0 61 00 00  
00F0D8  1  F8 62 00 00  
00F0E0  1  F0 F0 64 00      .byte $F0,$F0,$64,$00,$F8,$F8,$65,$00,$F8,$F0,$66,$00,$00,$F8,$67,$00   ; $F0E0
00F0E4  1  F8 F8 65 00  
00F0E8  1  F8 F0 66 00  
00F0F0  1  00 05 F0 63      .byte $00,$05,$F0,$63,$40,$08,$F0,$64,$40,$00,$F8,$65,$40,$00,$F0,$66   ; $F0F0
00F0F4  1  40 08 F0 64  
00F0F8  1  40 00 F8 65  
00F100  1               
00F100  1               RenderingAnimationData_F100:          ; $F100
00F100  1  40 F8 F8 67      .byte $40,$F8,$F8,$67,$40,$F8,$04,$F0,$44,$00,$F8,$F8,$95,$00,$F8,$F0   ; $F100
00F104  1  40 F8 04 F0  
00F108  1  44 00 F8 F8  
00F110  1  46 00 00 F8      .byte $46,$00,$00,$F8,$96,$00,$00,$04,$F0,$40,$00,$F8,$F8,$41,$00,$F8   ; $F110
00F114  1  96 00 00 04  
00F118  1  F0 40 00 F8  
00F120  1  F0 42 00 00      .byte $F0,$42,$00,$00,$F8,$43,$00,$00,$04,$F0,$44,$00,$F8,$F8,$45,$00   ; $F120
00F124  1  F8 43 00 00  
00F128  1  04 F0 44 00  
00F130  1  F8 F0 46 00      .byte $F8,$F0,$46,$00,$00,$F8,$47,$00,$00,$05,$F1,$97,$00,$F8,$F9,$7E   ; $F130
00F134  1  00 F8 47 00  
00F138  1  00 05 F1 97  
00F140  1  00 F8 E9 7F      .byte $00,$F8,$E9,$7F,$00,$00,$F1,$10,$00,$00,$F9,$81,$00,$00,$05,$F0   ; $F140
00F144  1  00 00 F1 10  
00F148  1  00 00 F9 81  
00F150  1  11 00 F8 F8      .byte $11,$00,$F8,$F8,$83,$00,$F8,$E8,$7F,$00,$00,$F0,$12,$00,$00,$F8   ; $F150
00F154  1  83 00 F8 E8  
00F158  1  7F 00 00 F0  
00F160  1  8E 00 00 05      .byte $8E,$00,$00,$05,$F0,$13,$00,$F8,$F8,$90,$00,$F8,$E8,$7F,$00,$00   ; $F160
00F164  1  F0 13 00 F8  
00F168  1  F8 90 00 F8  
00F170  1  F0 14 00 00      .byte $F0,$14,$00,$00,$F8,$92,$00,$00,$05,$F1,$97,$40,$00,$F9,$7E,$40   ; $F170
00F174  1  F8 92 00 00  
00F178  1  05 F1 97 40  
00F180  1  00 E9 7F 40      .byte $00,$E9,$7F,$40,$F8,$F1,$10,$40,$F8,$F9,$81,$40,$F8,$05,$F0,$11   ; $F180
00F184  1  F8 F1 10 40  
00F188  1  F8 F9 81 40  
00F190  1  40 00 F8 83      .byte $40,$00,$F8,$83,$40,$00,$E8,$7F,$40,$F8,$F0,$12,$40,$F8,$F8,$8E   ; $F190
00F194  1  40 00 E8 7F  
00F198  1  40 F8 F0 12  
00F1A0  1  40 F8 05 F0      .byte $40,$F8,$05,$F0,$13,$40,$00,$F8,$90,$40,$00,$E8,$7F,$40,$F8,$F0   ; $F1A0
00F1A4  1  13 40 00 F8  
00F1A8  1  90 40 00 E8  
00F1B0  1  14 40 F8 F8      .byte $14,$40,$F8,$F8,$92,$40,$F8,$05,$F0,$15,$40,$00,$F8,$71,$40,$00   ; $F1B0
00F1B4  1  92 40 F8 05  
00F1B8  1  F0 15 40 00  
00F1C0  1  E8 72 40 F8      .byte $E8,$72,$40,$F8,$F0,$E5,$40,$F8,$F8,$74,$40,$F8,$05,$F0,$15,$40   ; $F1C0
00F1C4  1  F0 E5 40 F8  
00F1C8  1  F8 74 40 F8  
00F1D0  1  00 F8 76 40      .byte $00,$F8,$76,$40,$00,$E8,$72,$40,$F8,$F0,$E5,$40,$F8,$F8,$78,$40   ; $F1D0
00F1D4  1  00 E8 72 40  
00F1D8  1  F8 F0 E5 40  
00F1E0  1  F8 05 F1 79      .byte $F8,$05,$F1,$79,$40,$00,$F9,$7A,$40,$00,$E9,$72,$40,$F8,$F1,$E6   ; $F1E0
00F1E4  1  40 00 F9 7A  
00F1E8  1  40 00 E9 72  
00F1F0  1  40 F8 F9 7C      .byte $40,$F8,$F9,$7C,$40,$F8,$05,$F0,$15,$00,$F8,$F8,$71,$00,$F8,$E8   ; $F1F0
00F1F4  1  40 F8 05 F0  
00F1F8  1  15 00 F8 F8  
00F200  1               
00F200  1               RenderingAnimationData_F200:          ; $F200
00F200  1  72 00 00 F0      .byte $72,$00,$00,$F0,$E5,$00,$00,$F8,$74,$00,$00,$05,$F0,$15,$00,$F8   ; $F200
00F204  1  E5 00 00 F8  
00F208  1  74 00 00 05  
00F210  1  F8 76 00 F8      .byte $F8,$76,$00,$F8,$E8,$72,$00,$00,$F0,$E5,$00,$00,$F8,$78,$00,$00   ; $F210
00F214  1  E8 72 00 00  
00F218  1  F0 E5 00 00  
00F220  1  05 F1 79 00      .byte $05,$F1,$79,$00,$F8,$F9,$7A,$00,$F8,$E9,$72,$00,$00,$F1,$E6,$00   ; $F220
00F224  1  F8 F9 7A 00  
00F228  1  F8 E9 72 00  
00F230  1  00 F9 7C 00      .byte $00,$F9,$7C,$00,$00,$04,$F0,$48,$00,$F8,$F8,$49,$00,$F8,$F0,$4A   ; $F230
00F234  1  00 04 F0 48  
00F238  1  00 F8 F8 49  
00F240  1  00 00 F8 4B      .byte $00,$00,$F8,$4B,$00,$00,$04,$F0,$4C,$00,$F8,$F8,$4D,$00,$F8,$F0   ; $F240
00F244  1  00 00 04 F0  
00F248  1  4C 00 F8 F8  
00F250  1  4E 00 00 F8      .byte $4E,$00,$00,$F8,$4F,$00,$00,$04,$F0,$4C,$40,$00,$F8,$4D,$40,$00   ; $F250
00F254  1  4F 00 00 04  
00F258  1  F0 4C 40 00  
00F260  1  F0 4E 40 F8      .byte $F0,$4E,$40,$F8,$F8,$4F,$40,$F8,$05,$F0,$50,$00,$F8,$F8,$51,$00   ; $F260
00F264  1  F8 4F 40 F8  
00F268  1  05 F0 50 00  
00F270  1  F8 E8 52 00      .byte $F8,$E8,$52,$00,$00,$F0,$53,$00,$00,$F8,$54,$00,$00,$05,$F0,$50   ; $F270
00F274  1  00 F0 53 00  
00F278  1  00 F8 54 00  
00F280  1  00 F8 F8 55      .byte $00,$F8,$F8,$55,$00,$F8,$E8,$52,$00,$00,$F0,$53,$00,$00,$F8,$56   ; $F280
00F284  1  00 F8 E8 52  
00F288  1  00 00 F0 53  
00F290  1  00 00 04 F0      .byte $00,$00,$04,$F0,$84,$00,$F8,$F8,$85,$00,$F8,$F0,$86,$00,$00,$F8   ; $F290
00F294  1  84 00 F8 F8  
00F298  1  85 00 F8 F0  
00F2A0  1  87 00 00 04      .byte $87,$00,$00,$04,$F8,$57,$40,$04,$F0,$58,$40,$00,$F8,$59,$40,$00   ; $F2A0
00F2A4  1  F8 57 40 04  
00F2A8  1  F0 58 40 00  
00F2B0  1  F8 5A 40 F8      .byte $F8,$5A,$40,$F8,$06,$F0,$EA,$02,$F8,$F8,$EB,$02,$F8,$E8,$EC,$02   ; $F2B0
00F2B4  1  06 F0 EA 02  
00F2B8  1  F8 F8 EB 02  
00F2C0  1  00 F0 F0 02      .byte $00,$F0,$F0,$02,$00,$F8,$EE,$02,$00,$F0,$F1,$02,$08,$06,$F0,$EA   ; $F2C0
00F2C4  1  00 F8 EE 02  
00F2C8  1  00 F0 F1 02  
00F2D0  1  02 F8 F8 EB      .byte $02,$F8,$F8,$EB,$02,$F8,$E8,$EC,$02,$00,$F0,$F0,$02,$00,$F8,$EE   ; $F2D0
00F2D4  1  02 F8 E8 EC  
00F2D8  1  02 00 F0 F0  
00F2E0  1  02 00 ED F2      .byte $02,$00,$ED,$F2,$02,$08,$04,$F0,$F4,$42,$F8,$F8,$F5,$42,$F8,$F0   ; $F2E0
00F2E4  1  02 08 04 F0  
00F2E8  1  F4 42 F8 F8  
00F2F0  1  F4 02 00 F8      .byte $F4,$02,$00,$F8,$F5,$02,$00,$04,$F0,$F6,$42,$F8,$F8,$F7,$42,$F8   ; $F2F0
00F2F4  1  F5 02 00 04  
00F2F8  1  F0 F6 42 F8  
00F300  1               
00F300  1               RenderingAnimationData_F300:          ; $F300
00F300  1  F0 F6 02 00      .byte $F0,$F6,$02,$00,$F8,$F7,$02,$00,$06,$F0,$EA,$02,$F8,$F8,$EB,$02   ; $F300
00F304  1  F8 F7 02 00  
00F308  1  06 F0 EA 02  
00F310  1  F8 E8 EC 02      .byte $F8,$E8,$EC,$02,$00,$F0,$ED,$02,$00,$F8,$EE,$02,$00,$F0,$EF,$02   ; $F310
00F314  1  00 F0 ED 02  
00F318  1  00 F8 EE 02  
00F320  1  08 04 F0 FC      .byte $08,$04,$F0,$FC,$02,$F8,$F8,$FD,$02,$F8,$F0,$FE,$02,$00,$F8,$FF   ; $F320
00F324  1  02 F8 F8 FD  
00F328  1  02 F8 F0 FE  
00F330  1  02 00 04 F0      .byte $02,$00,$04,$F0,$F8,$42,$F8,$F8,$F9,$42,$F8,$F0,$F8,$02,$00,$F8   ; $F330
00F334  1  F8 42 F8 F8  
00F338  1  F9 42 F8 F0  
00F340  1  F9 02 00 04      .byte $F9,$02,$00,$04,$F0,$FA,$42,$F8,$F8,$FB,$42,$F8,$F0,$FA,$02,$00   ; $F340
00F344  1  F0 FA 42 F8  
00F348  1  F8 FB 42 F8  
00F350  1  F8 FB 02 00      .byte $F8,$FB,$02,$00,$02,$F0,$1C,$01,$FC,$F8,$1D,$01,$FC,$02,$F0,$1E   ; $F350
00F354  1  02 F0 1C 01  
00F358  1  FC F8 1D 01  
00F360  1  01 FC F8 1F      .byte $01,$FC,$F8,$1F,$01,$FC,$02,$F0,$20,$01,$FC,$F8,$21,$01,$FC,$02   ; $F360
00F364  1  01 FC 02 F0  
00F368  1  20 01 FC F8  
00F370  1  F0 1C 41 FC      .byte $F0,$1C,$41,$FC,$F8,$1D,$41,$FC,$02,$F0,$1E,$41,$FC,$F8,$1F,$41   ; $F370
00F374  1  F8 1D 41 FC  
00F378  1  02 F0 1E 41  
00F380  1  FC 02 F0 20      .byte $FC,$02,$F0,$20,$41,$FC,$F8,$21,$41,$FC,$02,$F0,$16,$41,$FC,$F8   ; $F380
00F384  1  41 FC F8 21  
00F388  1  41 FC 02 F0  
00F390  1  17 41 FC 02      .byte $17,$41,$FC,$02,$F0,$18,$41,$FC,$F8,$19,$41,$FC,$02,$F0,$1A,$41   ; $F390
00F394  1  F0 18 41 FC  
00F398  1  F8 19 41 FC  
00F3A0  1  FC F8 1B 41      .byte $FC,$F8,$1B,$41,$FC,$02,$F0,$16,$01,$FC,$F8,$17,$01,$FC,$02,$F0   ; $F3A0
00F3A4  1  FC 02 F0 16  
00F3A8  1  01 FC F8 17  
00F3B0  1  18 01 FC F8      .byte $18,$01,$FC,$F8,$19,$01,$FC,$02,$F0,$1A,$01,$FC,$F8,$1B,$01,$FC   ; $F3B0
00F3B4  1  19 01 FC 02  
00F3B8  1  F0 1A 01 FC  
00F3C0  1  02 F0 24 00      .byte $02,$F0,$24,$00,$FC,$F8,$25,$00,$FC,$02,$F0,$22,$00,$FC,$F8,$23   ; $F3C0
00F3C4  1  FC F8 25 00  
00F3C8  1  FC 02 F0 22  
00F3D0  1  00 FC 02 F0      .byte $00,$FC,$02,$F0,$3D,$00,$FC,$F8,$3E,$00,$FC,$02,$F0,$00,$00,$FC   ; $F3D0
00F3D4  1  3D 00 FC F8  
00F3D8  1  3E 00 FC 02  
00F3E0  1  F8 01 00 FC      .byte $F8,$01,$00,$FC,$02,$F0,$02,$00,$FC,$F8,$03,$00,$FC,$02,$F0,$04   ; $F3E0
00F3E4  1  02 F0 02 00  
00F3E8  1  FC F8 03 00  
00F3F0  1  00 FC F8 05      .byte $00,$FC,$F8,$05,$00,$FC,$02,$F0,$06,$00,$FC,$F8,$07,$00,$FC,$02   ; $F3F0
00F3F4  1  00 FC 02 F0  
00F3F8  1  06 00 FC F8  
00F400  1               
00F400  1               RenderingAnimationData_F400:          ; $F400
00F400  1  F0 08 00 FC      .byte $F0,$08,$00,$FC,$F8,$09,$00,$FC,$02,$F0,$0A,$40,$FC,$F8,$0B,$40   ; $F400
00F404  1  F8 09 00 FC  
00F408  1  02 F0 0A 40  
00F410  1  FC 02 F0 0C      .byte $FC,$02,$F0,$0C,$40,$FC,$F8,$0D,$40,$FC,$02,$F0,$0E,$40,$FC,$F8   ; $F410
00F414  1  40 FC F8 0D  
00F418  1  40 FC 02 F0  
00F420  1  0F 40 FC 02      .byte $0F,$40,$FC,$02,$F0,$0A,$00,$FC,$F8,$0B,$00,$FC,$02,$F0,$0C,$00   ; $F420
00F424  1  F0 0A 00 FC  
00F428  1  F8 0B 00 FC  
00F430  1  FC F8 0D 00      .byte $FC,$F8,$0D,$00,$FC,$02,$F0,$0E,$00,$FC,$F8,$0F,$00,$FC,$02,$F0   ; $F430
00F434  1  FC 02 F0 0E  
00F438  1  00 FC F8 0F  
00F440  1  00 00 FC F8      .byte $00,$00,$FC,$F8,$3C,$00,$FC,$02,$F0,$28,$02,$FC,$F8,$29,$02,$FC   ; $F440
00F444  1  3C 00 FC 02  
00F448  1  F0 28 02 FC  
00F450  1  02 F0 26 02      .byte $02,$F0,$26,$02,$FC,$F8,$27,$02,$FC,$02,$F0,$2A,$02,$FC,$F8,$2B   ; $F450
00F454  1  FC F8 27 02  
00F458  1  FC 02 F0 2A  
00F460  1  02 FC 02 F0      .byte $02,$FC,$02,$F0,$2C,$02,$FC,$F8,$2D,$02,$FC,$02,$F0,$2E,$02,$FC   ; $F460
00F464  1  2C 02 FC F8  
00F468  1  2D 02 FC 02  
00F470  1  F8 2D 02 FC      .byte $F8,$2D,$02,$FC,$03,$F0,$31,$02,$FC,$F8,$32,$02,$FC,$F8,$33,$02   ; $F470
00F474  1  03 F0 31 02  
00F478  1  FC F8 32 02  
00F480  1  04 02 F0 2F      .byte $04,$02,$F0,$2F,$02,$FC,$F8,$30,$02,$FC,$02,$F0,$34,$02,$FC,$F8   ; $F480
00F484  1  02 FC F8 30  
00F488  1  02 FC 02 F0  
00F490  1  35 02 FC 01      .byte $35,$02,$FC,$01,$F8,$36,$03,$00,$04,$FF,$36,$C3,$F8,$F7,$36,$43   ; $F490
00F494  1  F8 36 03 00  
00F498  1  04 FF 36 C3  
00F4A0  1  F8 FF 36 83      .byte $F8,$FF,$36,$83,$00,$F7,$36,$03,$00,$04,$FE,$37,$C3,$F8,$F6,$37   ; $F4A0
00F4A4  1  00 F7 36 03  
00F4A8  1  00 04 FE 37  
00F4B0  1  43 F8 FE 37      .byte $43,$F8,$FE,$37,$83,$00,$F6,$37,$03,$00,$01,$F9,$38,$03,$FD,$01   ; $F4B0
00F4B4  1  83 00 F6 37  
00F4B8  1  03 00 01 F9  
00F4C0  1  F8 39 03 FD      .byte $F8,$39,$03,$FD,$04,$F0,$3A,$03,$F8,$F0,$3A,$43,$00,$F8,$3A,$83   ; $F4C0
00F4C4  1  04 F0 3A 03  
00F4C8  1  F8 F0 3A 43  
00F4D0  1  F8 F8 3A C3      .byte $F8,$F8,$3A,$C3,$00,$01,$F8,$36,$02,$00,$02,$F8,$36,$02,$00,$F8   ; $F4D0
00F4D4  1  00 01 F8 36  
00F4D8  1  02 00 02 F8  
00F4E0  1  36 42 F8 02      .byte $36,$42,$F8,$02,$F9,$37,$02,$00,$FF,$37,$C2,$F8,$01,$FE,$3B,$02   ; $F4E0
00F4E4  1  F9 37 02 00  
00F4E8  1  FF 37 C2 F8  
00F4F0  1  FC 00 3F 00      .byte $FC,$00,$3F,$00,$20,$30,$18,$1A,$07,$30,$01,$1A,$28,$30,$0F,$1A   ; $F4F0
00F4F4  1  20 30 18 1A  
00F4F8  1  07 30 01 1A  
00F500  1               
00F500  1               RenderingAnimationData_F500:          ; $F500
00F500  1  30 30 0F 2C      .byte $30,$30,$0F,$2C,$28,$30,$16,$27,$30,$30,$0F,$27,$30,$30,$11,$27   ; $F500
00F504  1  28 30 16 27  
00F508  1  30 30 0F 27  
00F510  1  0F 30 28 22      .byte $0F,$30,$28,$22,$30,$2B,$C0,$60,$00,$2B,$E0,$60,$00,$2B,$E8,$02   ; $F510
00F514  1  30 2B C0 60  
00F518  1  00 2B E0 60  
00F520  1  88 22 2B F0      .byte $88,$22,$2B,$F0,$02,$88,$22,$2B,$F5,$03,$88,$AA,$22,$2B,$E3,$42   ; $F520
00F524  1  02 88 22 2B  
00F528  1  F5 03 88 AA  
00F530  1  AA 23 E0 60      .byte $AA,$23,$E0,$60,$00,$23,$C0,$48,$FF,$23,$C8,$08,$5F,$5F,$5B,$5A   ; $F530
00F534  1  00 23 C0 48  
00F538  1  FF 23 C8 08  
00F540  1  5A 5E 5F 5F      .byte $5A,$5E,$5F,$5F,$23,$D0,$51,$55,$23,$DA,$44,$AA,$23,$E7,$01,$55   ; $F540
00F544  1  23 D0 51 55  
00F548  1  23 DA 44 AA  
00F550  1  23 F0 02 88      .byte $23,$F0,$02,$88,$22,$23,$F5,$03,$88,$AA,$22,$2A,$AD,$06,$B2,$34   ; $F550
00F554  1  22 23 F5 03  
00F558  1  88 AA 22 2A  
00F560  1  25 25 BD C0      .byte $25,$25,$BD,$C0,$2A,$CC,$08,$B0,$B3,$B6,$B9,$BB,$BE,$C1,$C4,$2A   ; $F560
00F564  1  2A CC 08 B0  
00F568  1  B3 B6 B9 BB  
00F570  1  EB 0A B0 25      .byte $EB,$0A,$B0,$25,$B4,$B7,$BA,$BC,$21,$C2,$25,$C4,$2B,$0B,$0A,$25   ; $F570
00F574  1  B4 B7 BA BC  
00F578  1  21 C2 25 C4  
00F580  1  25 B5 B8 25      .byte $25,$B5,$B8,$25,$25,$BF,$C3,$25,$25,$2B,$2B,$0A,$B1,$25,$25,$B4   ; $F580
00F584  1  25 BF C3 25  
00F588  1  25 2B 2B 0A  
00F590  1  25 25 C2 25      .byte $25,$25,$C2,$25,$25,$C5,$2B,$4C,$08,$B1,$25,$B5,$C6,$C6,$C3,$25   ; $F590
00F594  1  25 C5 2B 4C  
00F598  1  08 B1 25 B5  
00F5A0  1  C5 2B 6D 06      .byte $C5,$2B,$6D,$06,$B1,$25,$25,$25,$25,$C5,$29,$4E,$04,$CB,$CC,$CD   ; $F5A0
00F5A4  1  B1 25 25 25  
00F5A8  1  25 C5 29 4E  
00F5B0  1  CE 29 6E 04      .byte $CE,$29,$6E,$04,$CF,$27,$27,$D0,$29,$8E,$04,$D1,$D2,$D3,$D4,$29   ; $F5B0
00F5B4  1  CF 27 27 D0  
00F5B8  1  29 8E 04 D1  
00F5C0  1  77 06 FE FF      .byte $77,$06,$FE,$FF,$DF,$E0,$C9,$CA,$29,$98,$05,$E1,$E2,$E3,$E4,$D8   ; $F5C0
00F5C4  1  DF E0 C9 CA  
00F5C8  1  29 98 05 E1  
00F5D0  1  29 B8 05 E5      .byte $29,$B8,$05,$E5,$E6,$E7,$E8,$E9,$29,$D8,$04,$C9,$EA,$EB,$E9,$28   ; $F5D0
00F5D4  1  E6 E7 E8 E9  
00F5D8  1  29 D8 04 C9  
00F5E0  1  AE 04 D5 D6      .byte $AE,$04,$D5,$D6,$D7,$D8,$28,$CE,$04,$D9,$DA,$DB,$DC,$28,$EC,$08   ; $F5E0
00F5E4  1  D7 D8 28 CE  
00F5E8  1  04 D9 DA DB  
00F5F0  1  FB FC FD DD      .byte $FB,$FC,$FD,$DD,$DE,$FE,$FF,$49,$29,$63,$06,$C7,$C8,$EC,$ED,$FC   ; $F5F0
00F5F4  1  DE FE FF 49  
00F5F8  1  29 63 06 C7  
00F600  1               
00F600  1               RenderingAnimationData_F600:          ; $F600
00F600  1  FD 29 83 05      .byte $FD,$29,$83,$05,$D5,$EE,$EF,$F0,$F1,$29,$A3,$05,$F2,$F3,$F4,$F5   ; $F600
00F604  1  D5 EE EF F0  
00F608  1  F1 29 A3 05  
00F610  1  F6 29 C4 04      .byte $F6,$29,$C4,$04,$F2,$F7,$F8,$C8,$29,$00,$02,$C7,$C8,$29,$21,$02   ; $F610
00F614  1  F2 F7 F8 C8  
00F618  1  29 00 02 C7  
00F620  1  C7 C8 29 42      .byte $C7,$C8,$29,$42,$02,$C7,$C8,$29,$E7,$02,$C7,$C8,$2A,$08,$02,$C7   ; $F620
00F624  1  02 C7 C8 29  
00F628  1  E7 02 C7 C8  
00F630  1  C8 2A 29 02      .byte $C8,$2A,$29,$02,$C7,$C8,$2A,$4A,$02,$C7,$C8,$2A,$6B,$02,$C7,$C8   ; $F630
00F634  1  C7 C8 2A 4A  
00F638  1  02 C7 C8 2A  
00F640  1  2A 8C 02 C7      .byte $2A,$8C,$02,$C7,$C8,$2A,$92,$02,$C9,$CA,$2A,$73,$02,$C9,$CA,$2A   ; $F640
00F644  1  C8 2A 92 02  
00F648  1  C9 CA 2A 73  
00F650  1  54 02 C9 CA      .byte $54,$02,$C9,$CA,$2A,$35,$02,$C9,$CA,$2A,$16,$02,$C9,$CA,$29,$F7   ; $F650
00F654  1  2A 35 02 C9  
00F658  1  CA 2A 16 02  
00F660  1  02 C9 CA 29      .byte $02,$C9,$CA,$29,$5C,$02,$C9,$CA,$29,$3D,$02,$C9,$CA,$29,$1E,$02   ; $F660
00F664  1  5C 02 C9 CA  
00F668  1  29 3D 02 C9  
00F670  1  C9 CA 29 48      .byte $C9,$CA,$29,$48,$02,$F9,$FA,$29,$29,$03,$FB,$FC,$FD,$29,$0B,$02   ; $F670
00F674  1  02 F9 FA 29  
00F678  1  29 03 FB FC  
00F680  1  F9 FA 29 13      .byte $F9,$FA,$29,$13,$02,$4A,$4B,$29,$34,$03,$FE,$FF,$49,$29,$56,$02   ; $F680
00F684  1  02 4A 4B 29  
00F688  1  34 03 FE FF  
00F690  1  4A 4B 2A 83      .byte $4A,$4B,$2A,$83,$01,$3B,$2B,$02,$83,$0B,$1C,$18,$2A,$A3,$C6,$25   ; $F690
00F694  1  01 3B 2B 02  
00F698  1  83 0B 1C 18  
00F6A0  1  2A A4 C6 25      .byte $2A,$A4,$C6,$25,$2A,$A5,$C6,$25,$2A,$E2,$44,$26,$2A,$A5,$C2,$00   ; $F6A0
00F6A4  1  2A A5 C6 25  
00F6A8  1  2A E2 44 26  
00F6B0  1  2B 16 48 25      .byte $2B,$16,$48,$25,$2B,$36,$48,$25,$2B,$56,$48,$25,$20,$4A,$4C,$37   ; $F6B0
00F6B4  1  2B 36 48 25  
00F6B8  1  2B 56 48 25  
00F6C0  1  20 6A 0C 33      .byte $20,$6A,$0C,$33,$29,$2A,$2B,$2C,$2D,$2E,$2F,$30,$31,$33,$35,$20   ; $F6C0
00F6C4  1  29 2A 2B 2C  
00F6C8  1  2D 2E 2F 30  
00F6D0  1  8A 4B 33 20      .byte $8A,$4B,$33,$20,$AA,$4B,$33,$20,$95,$C2,$28,$20,$56,$84,$C8,$36   ; $F6D0
00F6D4  1  AA 4B 33 20  
00F6D8  1  95 C2 28 20  
00F6E0  1  36 36 20 A4      .byte $36,$36,$20,$A4,$05,$38,$26,$38,$26,$38,$20,$B7,$05,$38,$26,$38   ; $F6E0
00F6E4  1  05 38 26 38  
00F6E8  1  26 38 20 B7  
00F6F0  1  26 38 20 C0      .byte $26,$38,$20,$C0,$60,$6A,$20,$E0,$7F,$6B,$21,$1F,$66,$6B,$21,$5B   ; $F6F0
00F6F4  1  60 6A 20 E0  
00F6F8  1  7F 6B 21 1F  
00F700  1               
00F700  1               RenderingAnimationData_F700:          ; $F700
00F700  1  47 6B 20 C8      .byte $47,$6B,$20,$C8,$03,$53,$50,$40,$20,$CB,$4A,$41,$20,$D5,$03,$42   ; $F700
00F704  1  03 53 50 40  
00F708  1  20 CB 4A 41  
00F710  1  70 73 20 E8      .byte $70,$73,$20,$E8,$03,$54,$50,$43,$20,$EB,$4A,$25,$20,$F5,$03,$43   ; $F710
00F714  1  03 54 50 43  
00F718  1  20 EB 4A 25  
00F720  1  70 74 21 09      .byte $70,$74,$21,$09,$03,$51,$44,$45,$21,$0C,$48,$46,$21,$14,$03,$47   ; $F720
00F724  1  03 51 44 45  
00F728  1  21 0C 48 46  
00F730  1  48 71 21 28      .byte $48,$71,$21,$28,$10,$55,$52,$56,$57,$17,$12,$17,$1D,$0E,$17,$0D   ; $F730
00F734  1  10 55 52 56  
00F738  1  57 17 12 17  
00F740  1  18 77 76 72      .byte $18,$77,$76,$72,$75,$21,$45,$07,$58,$59,$5A,$5B,$5C,$5D,$5E,$21   ; $F740
00F744  1  75 21 45 07  
00F748  1  58 59 5A 5B  
00F750  1  54 07 7E 7D      .byte $54,$07,$7E,$7D,$7C,$7B,$7A,$79,$78,$21,$63,$05,$62,$61,$25,$5F   ; $F750
00F754  1  7C 7B 7A 79  
00F758  1  78 21 63 05  
00F760  1  60 21 78 0F      .byte $60,$21,$78,$0F,$80,$7F,$25,$81,$82,$87,$6B,$6B,$6B,$62,$63,$25   ; $F760
00F764  1  80 7F 25 81  
00F768  1  82 87 6B 6B  
00F770  1  25 24 23 21      .byte $25,$24,$23,$21,$99,$0C,$1A,$1F,$25,$25,$83,$82,$6B,$61,$25,$64   ; $F770
00F774  1  99 0C 1A 1F  
00F778  1  25 25 83 82  
00F780  1  25 66 21 BB      .byte $25,$66,$21,$BB,$09,$86,$25,$84,$25,$81,$25,$25,$64,$66,$21,$DC   ; $F780
00F784  1  09 86 25 84  
00F788  1  25 81 25 25  
00F790  1  07 86 84 25      .byte $07,$86,$84,$25,$25,$25,$25,$65,$21,$FD,$07,$85,$25,$25,$25,$66   ; $F790
00F794  1  25 25 25 65  
00F798  1  21 FD 07 85  
00F7A0  1  6E 6F 22 1C      .byte $6E,$6F,$22,$1C,$0A,$4E,$4F,$86,$25,$66,$26,$26,$26,$6C,$6D,$20   ; $F7A0
00F7A4  1  0A 4E 4F 86  
00F7A8  1  25 66 26 26  
00F7B0  1  82 88 69 69      .byte $82,$88,$69,$69,$68,$67,$67,$67,$67,$67,$20,$9D,$87,$89,$89,$88   ; $F7B0
00F7B4  1  68 67 67 67  
00F7B8  1  67 67 20 9D  
00F7C0  1  87 87 87 87      .byte $87,$87,$87,$87,$22,$2E,$04,$8A,$8B,$8C,$8D,$22,$3A,$06,$4C,$4D   ; $F7C0
00F7C4  1  22 2E 04 8A  
00F7C8  1  8B 8C 8D 22  
00F7D0  1  26 26 26 86      .byte $26,$26,$26,$86,$22,$45,$02,$6E,$6F,$22,$4D,$06,$AA,$AB,$8E,$8F   ; $F7D0
00F7D4  1  22 45 02 6E  
00F7D8  1  6F 22 4D 06  
00F7E0  1  A8 A9 22 59      .byte $A8,$A9,$22,$59,$02,$4E,$4F,$22,$67,$12,$6C,$6D,$26,$26,$AA,$AB   ; $F7E0
00F7E4  1  02 4E 4F 22  
00F7E8  1  67 12 6C 6D  
00F7F0  1  26 26 9C 9E      .byte $26,$26,$9C,$9E,$26,$26,$A8,$A9,$26,$26,$4C,$4D,$22,$88,$03,$6E   ; $F7F0
00F7F4  1  26 26 A8 A9  
00F7F8  1  26 26 4C 4D  
00F800  1               
00F800  1               RenderingAnimationData_F800:          ; $F800
00F800  1  A4 A6 22 8F      .byte $A4,$A6,$22,$8F,$02,$9D,$9F,$22,$95,$03,$A0,$A2,$4F,$22,$A9,$03   ; $F800
00F804  1  02 9D 9F 22  
00F808  1  95 03 A0 A2  
00F810  1  A5 A7 6D 22      .byte $A5,$A7,$6D,$22,$B4,$03,$4C,$A1,$A3,$22,$CB,$02,$6E,$6F,$22,$D3   ; $F810
00F814  1  B4 03 4C A1  
00F818  1  A3 22 CB 02  
00F820  1  02 4E 4F 22      .byte $02,$4E,$4F,$22,$ED,$06,$6C,$6D,$26,$26,$4C,$4D,$23,$0E,$04,$90   ; $F820
00F824  1  ED 06 6C 6D  
00F828  1  26 26 4C 4D  
00F830  1  93 96 99 23      .byte $93,$96,$99,$23,$2E,$04,$91,$94,$97,$9A,$23,$4E,$04,$92,$95,$98   ; $F830
00F834  1  2E 04 91 94  
00F838  1  97 9A 23 4E  
00F840  1  9B 23 02 83      .byte $9B,$23,$02,$83,$0B,$1C,$18,$23,$03,$43,$25,$23,$23,$43,$25,$23   ; $F840
00F844  1  0B 1C 18 23  
00F848  1  03 43 25 23  
00F850  1  43 43 25 23      .byte $43,$43,$25,$23,$16,$48,$25,$23,$36,$48,$25,$23,$56,$48,$25,$21   ; $F850
00F854  1  16 48 25 23  
00F858  1  36 48 25 23  
00F860  1  88 10 1C 0E      .byte $88,$10,$1C,$0E,$15,$0E,$0C,$1D,$25,$22,$18,$1E,$1B,$25,$1D,$0E   ; $F860
00F864  1  15 0E 0C 1D  
00F868  1  25 22 18 1E  
00F870  1  0A 16 21 A8      .byte $0A,$16,$21,$A8,$50,$25,$21,$C8,$50,$25,$21,$CA,$0B,$0A,$25,$0C   ; $F870
00F874  1  50 25 21 C8  
00F878  1  50 25 21 CA  
00F880  1  25 0D 25 19      .byte $25,$0D,$25,$19,$25,$1B,$25,$22,$21,$E8,$50,$25,$00,$3F,$00,$14   ; $F880
00F884  1  25 1B 25 22  
00F888  1  21 E8 50 25  
00F890  1  0F 0F 11 30      .byte $0F,$0F,$11,$30,$0F,$0F,$0F,$24,$0F,$0F,$0F,$27,$0F,$0F,$0F,$30   ; $F890
00F894  1  0F 0F 0F 24  
00F898  1  0F 0F 0F 27  
00F8A0  1  0F 0F 11 30      .byte $0F,$0F,$11,$30,$23,$C0,$6A,$00,$23,$EA,$01,$99,$23,$EB,$45,$AA   ; $F8A0
00F8A4  1  23 C0 6A 00  
00F8A8  1  23 EA 01 99  
00F8B0  1  23 F0 50 FF      .byte $23,$F0,$50,$FF,$20,$A4,$53,$AE,$20,$E4,$53,$AE,$21,$24,$53,$AE   ; $F8B0
00F8B4  1  20 A4 53 AE  
00F8B8  1  20 E4 53 AE  
00F8C0  1  21 69 48 AE      .byte $21,$69,$48,$AE,$21,$A9,$49,$AE,$21,$E9,$43,$AE,$21,$F3,$49,$AE   ; $F8C0
00F8C4  1  21 A9 49 AE  
00F8C8  1  21 E9 43 AE  
00F8D0  1  20 A4 C5 AE      .byte $20,$A4,$C5,$AE,$20,$C9,$CA,$AE,$20,$CC,$C4,$AE,$21,$8E,$C4,$AE   ; $F8D0
00F8D4  1  20 C9 CA AE  
00F8D8  1  20 CC C4 AE  
00F8E0  1  21 91 C4 AE      .byte $21,$91,$C4,$AE,$20,$B3,$CB,$AE,$21,$78,$C5,$AE,$20,$A7,$48,$25   ; $F8E0
00F8E4  1  20 B3 CB AE  
00F8E8  1  21 78 C5 AE  
00F8F0  1  20 E7 42 25      .byte $20,$E7,$42,$25,$21,$27,$42,$25,$21,$2A,$42,$25,$21,$6C,$47,$25   ; $F8F0
00F8F4  1  21 27 42 25  
00F8F8  1  21 2A 42 25  
00F900  1               
00F900  1               RenderingAnimationData_F900:          ; $F900
00F900  1  21 AC 42 25      .byte $21,$AC,$42,$25,$21,$F7,$01,$25,$21,$49,$4B,$25,$20,$ED,$C3,$25   ; $F900
00F904  1  21 F7 01 25  
00F908  1  21 49 4B 25  
00F910  1  20 B2 C5 25      .byte $20,$B2,$C5,$25,$20,$AE,$C5,$25,$20,$B1,$C5,$25,$20,$63,$5A,$26   ; $F910
00F914  1  20 AE C5 25  
00F918  1  20 B1 C5 25  
00F920  1  22 23 5A 26      .byte $22,$23,$5A,$26,$20,$82,$CD,$26,$20,$9D,$CD,$26,$22,$AA,$0D,$01   ; $F920
00F924  1  20 82 CD 26  
00F928  1  20 9D CD 26  
00F930  1  25 19 15 0A      .byte $25,$19,$15,$0A,$22,$0E,$1B,$25,$10,$0A,$16,$0E,$22,$EA,$0D,$02   ; $F930
00F934  1  22 0E 1B 25  
00F938  1  10 0A 16 0E  
00F940  1  25 19 15 0A      .byte $25,$19,$15,$0A,$22,$0E,$1B,$25,$10,$0A,$16,$0E,$00   ; $F940
00F944  1  22 0E 1B 25  
00F948  1  10 0A 16 0E  
00F94D  1               
00F94D  1               FrameOamTemplate_F94D:                ; $F94D
00F94D  1                   ; 22 OAM entries x 4 bytes = 88 bytes.
00F94D  1                   ; Entry format: Y, tile, attributes, X.
00F94D  1  2F AE 00 34      .byte $2F,$AE,$00,$34,$3B,$AE,$00,$38,$43,$AE,$00,$38,$27,$AE,$00,$4C   ; $F94D
00F951  1  3B AE 00 38  
00F955  1  43 AE 00 38  
00F95D  1  27 AE 00 54      .byte $27,$AE,$00,$54,$27,$AE,$00,$5C,$2B,$AE,$00,$70,$33,$AE,$00,$70   ; $F95D
00F961  1  27 AE 00 5C  
00F965  1  2B AE 00 70  
00F96D  1  43 AE 00 70      .byte $43,$AE,$00,$70,$2B,$AE,$00,$88,$3B,$AE,$00,$88,$43,$AE,$00,$88   ; $F96D
00F971  1  2B AE 00 88  
00F975  1  3B AE 00 88  
00F97D  1  5F AE 00 5C      .byte $5F,$AE,$00,$5C,$6B,$AE,$00,$60,$73,$AE,$00,$60,$57,$AE,$00,$74   ; $F97D
00F981  1  6B AE 00 60  
00F985  1  73 AE 00 60  
00F98D  1  57 AE 00 7C      .byte $57,$AE,$00,$7C,$57,$AE,$00,$84,$17,$13,$00,$10,$17,$13,$40,$E8   ; $F98D
00F991  1  57 AE 00 84  
00F995  1  17 13 00 10  
00F99D  1  87 13 80 10      .byte $87,$13,$80,$10,$87,$13,$C0,$E8   ; $F99D
00F9A1  1  87 13 C0 E8  
00F9A5  1               
00F9A5  1               RenderingAnimationData_F9A5:          ; $F9A5
00F9A5  1  FF FF FF FF      .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF   ; $F9A5
00F9A9  1  FF FF FF FF  
00F9AD  1  FF FF FF FF  
00F9B5  1  FF FF FF FF      .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF   ; $F9B5
00F9B9  1  FF FF FF FF  
00F9BD  1  FF FF FF FF  
00F9C5  1  FF FF FF FF      .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF   ; $F9C5
00F9C9  1  FF FF FF FF  
00F9CD  1  FF FF FF     
00F9D0  1               
00F9D0  1               ; ============================================================================
00F9D0  1               ; $F9D0-$F9F4
00F9D0  1               ; Initialize the audio engine and APU output state.
00F9D0  1               ;
00F9D0  1               ; Operation:
00F9D0  1               ;   1. Configure the APU frame counter.
00F9D0  1               ;   2. Initialize the main audio subsystem through $FB05.
00F9D0  1               ;   3. Clear three audio/engine state bytes.
00F9D0  1               ;   4. Decrement the startup value at $07FF up to two times.
00F9D0  1               ;   5. Write the resulting value to the APU DMC direct-load register.
00F9D0  1               ;
00F9D0  1               ; Exit:
00F9D0  1               ;   A = final value from $07FF
00F9D0  1               ; ============================================================================
00F9D0  1               
00F9D0  1               ; ----------------------------------------------------------------------------
00F9D0  1               ; Contract:
00F9D0  1               ;   Description: Initializes Audio Engine.
00F9D0  1               ;   Entry: Registers: A; Memory: $07ff
00F9D0  1               ;   Returns/products: Registers/clobbers: A
00F9D0  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00F9D0  1               ;   Memory effects: $4017, $ff, pendingaudioflags, $fd, $4011
00F9D0  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00F9D0  1               ;          comparison, load, or store path and are not a stable API product.
00F9D0  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00F9D0  1               ; ----------------------------------------------------------------------------
00F9D0  1               InitializeAudioEngine:          ; $F9D0
00F9D0  1  A9 C0            lda #$C0                    ; $F9D0: A9 C0
00F9D2  1  8D 17 40         sta $4017                   ; $F9D2: 8D 17 40
00F9D5  1                                               ; Configure the APU frame counter:
00F9D5  1                                               ;   bit 7 = five-step sequence
00F9D5  1                                               ;   bit 6 = inhibit frame IRQ
00F9D5  1               
00F9D5  1               ; ----------------------------------------------------------------------------
00F9D5  1               ; Initialize the remaining audio subsystem state.
00F9D5  1               ; ----------------------------------------------------------------------------
00F9D5  1               
00F9D5  1  20 05 FB         jsr UpdateAudioEngine                   ; $F9D5: 20 05 FB
00F9D8  1               
00F9D8  1               ; ----------------------------------------------------------------------------
00F9D8  1               ; Clear shared audio and engine state.
00F9D8  1               ; ----------------------------------------------------------------------------
00F9D8  1               
00F9D8  1  A9 00            lda #$00                    ; $F9D8: A9 00
00F9DA  1               
00F9DA  1  85 FF            sta RenderStateFlags                     ; $F9DA: 85 FF
00F9DC  1  85 FE            sta PendingAudioFlags             ; $F9DC: 85 FE
00F9DE  1  85 FD            sta $FD                     ; $F9DE: 85 FD
00F9E0  1               
00F9E0  1               ; ----------------------------------------------------------------------------
00F9E0  1               ; Apply a short two-step countdown to the value at $07FF.
00F9E0  1               ;
00F9E0  1               ; If the initial value is zero:
00F9E0  1               ;   no decrement occurs.
00F9E0  1               ;
00F9E0  1               ; If the initial value is one:
00F9E0  1               ;   one decrement occurs, producing zero.
00F9E0  1               ;
00F9E0  1               ; If the initial value is two or greater:
00F9E0  1               ;   two decrements occur.
00F9E0  1               ; ----------------------------------------------------------------------------
00F9E0  1               
00F9E0  1  AD FF 07         lda $07FF                   ; $F9E0: AD FF 07
00F9E3  1  F0 08            beq InitializeAudioEngine_WriteDmc
00F9E5  1                                               ; $F9E3: F0 08
00F9E5  1               
00F9E5  1  CE FF 07         dec $07FF                   ; $F9E5: CE FF 07
00F9E8  1  F0 03            beq InitializeAudioEngine_WriteDmc
00F9EA  1                                               ; $F9E8: F0 03
00F9EA  1               
00F9EA  1  CE FF 07         dec $07FF                   ; $F9EA: CE FF 07
00F9ED  1               
00F9ED  1               ; ----------------------------------------------------------------------------
00F9ED  1               ; Write the resulting value to the APU DMC direct-load register.
00F9ED  1               ;
00F9ED  1               ; $4011 controls the seven-bit DMC output level.
00F9ED  1               ; ----------------------------------------------------------------------------
00F9ED  1               
00F9ED  1               InitializeAudioEngine_WriteDmc: ; $F9ED
00F9ED  1  AD FF 07         lda $07FF                   ; $F9ED: AD FF 07
00F9F0  1  8D 11 40         sta $4011                   ; $F9F0: 8D 11 40
00F9F3  1               
00F9F3  1  60               rts                         ; $F9F3: 60
00F9F4  1               
00F9F4  1               ; ============================================================================
00F9F4  1               ; $F9F4-$F9FF
00F9F4  1               ; Unused/padding bytes.
00F9F4  1               ; ============================================================================
00F9F4  1               
00F9F4  1               AudioPadding_F9F4:              ; $F9F4
00F9F4  1  FF FF FF FF      .byte $FF,$FF,$FF,$FF
00F9F8  1  FF FF FF FF      .byte $FF,$FF,$FF,$FF
00F9FC  1  FF FF FF FF      .byte $FF,$FF,$FF,$FF
00FA00  1               
00FA00  1               ; ============================================================================
00FA00  1               ; $FA00-$FA5F
00FA00  1               ; Audio engine lookup data.
00FA00  1               ;
00FA00  1               ; This region contains several adjacent tables used by the audio routines that
00FA00  1               ; follow. The first portion consists primarily of little-endian timer or period
00FA00  1               ; values, followed by smaller rhythm, duration, envelope, or index tables.
00FA00  1               ;
00FA00  1               ; Keep the exact byte layout because later routines reference internal
00FA00  1               ; addresses such as $FA01 and $FA4A directly.
00FA00  1               ; ============================================================================
00FA00  1               
00FA00  1               AudioLookupData_FA00:           ; $FA00
00FA00  1  07 F0 00 69      .byte $07,$F0,$00,$69,$00,$00,$00,$D4
00FA04  1  00 00 00 D4  
00FA08  1  00 BD 00 B2      .byte $00,$BD,$00,$B2,$00,$A8,$00,$9F
00FA0C  1  00 A8 00 9F  
00FA10  1  00 96 00 8D      .byte $00,$96,$00,$8D,$00,$7E,$00,$70
00FA14  1  00 7E 00 70  
00FA18  1  01 AB 01 93      .byte $01,$AB,$01,$93,$01,$7C,$01,$67
00FA1C  1  01 7C 01 67  
00FA20  1  01 52 01 3F      .byte $01,$52,$01,$3F,$01,$2D,$01,$1C
00FA24  1  01 2D 01 1C  
00FA28  1  01 0C 00 FD      .byte $01,$0C,$00,$FD,$00,$EE,$00,$E1
00FA2C  1  00 EE 00 E1  
00FA30  1  03 57 02 F9      .byte $03,$57,$02,$F9,$02,$A6,$02,$80
00FA34  1  02 A6 02 80  
00FA38  1  02 3A 01 FC      .byte $02,$3A,$01,$FC,$01,$C4,$00,$5E
00FA3C  1  01 C4 00 5E  
00FA40  1  00 53 00 4F      .byte $00,$53,$00,$4F,$00,$4A,$00,$3E
00FA44  1  00 4A 00 3E  
00FA48  1  00 20 05 0A      .byte $00,$20,$05,$0A,$14,$28,$0D,$21
00FA4C  1  14 28 0D 21  
00FA50  1  06 07 06 0C      .byte $06,$07,$06,$0C,$18,$30,$10,$24
00FA54  1  18 30 10 24  
00FA58  1  48 08 FF FF      .byte $48,$08,$FF,$FF,$FF,$FF,$FF,$FF
00FA5C  1  FF FF FF FF  
00FA60  1               
00FA60  1               ; ============================================================================
00FA60  1               ; Useful internal table bases referenced by later audio routines.
00FA60  1               ; ============================================================================
00FA60  1               
00FA60  1               ApuTimerTableHighBytes  = $FA00
00FA60  1               ApuTimerTableLowBytes = $FA01
00FA60  1               
00FA60  1               NoteDurationTable = $FA4A
00FA60  1               ; ============================================================================
00FA60  1               ; $FA60-$FA70
00FA60  1               ; Write preset or caller-supplied control values to pulse channel 1.
00FA60  1               ; ============================================================================
00FA60  1               
00FA60  1               ConfigurePulse1ControlPreset:   ; $FA60
00FA60  1  A2 90            ldx #$90                    ; $FA60: A2 90
00FA62  1  D0 09            bne WritePulse1Control      ; $FA62: D0 09
00FA64  1                                               ; Target $FA6D.
00FA64  1               
00FA64  1               ; ============================================================================
00FA64  1               ; $FA64-$FA67
00FA64  1               ; Write preset control value $90 to pulse channel 2.
00FA64  1               ; ============================================================================
00FA64  1               
00FA64  1               ConfigurePulse2ControlPreset:   ; $FA64
00FA64  1  A2 90            ldx #$90                    ; $FA64: A2 90
00FA66  1  D0 0E            bne WritePulse2Control      ; $FA66: D0 0E
00FA68  1                                               ; Target $FA76.
00FA68  1               
00FA68  1               ; ============================================================================
00FA68  1               ; $FA68-$FA70
00FA68  1               ; Write a caller-supplied pulse 1 control value and reset its sweep state.
00FA68  1               ;
00FA68  1               ; Entry:
00FA68  1               ;   X = value for $4000
00FA68  1               ; ============================================================================
00FA68  1               
00FA68  1               ; ----------------------------------------------------------------------------
00FA68  1               ; Contract:
00FA68  1               ;   Description: Writes Pulse 1 Sweep And Control.
00FA68  1               ;   Entry: Registers: X, Y
00FA68  1               ;   Returns/products: Registers/clobbers: Y
00FA68  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00FA68  1               ;   Memory effects: $4001, $4000
00FA68  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00FA68  1               ;          comparison, load, or store path and are not a stable API product.
00FA68  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00FA68  1               ; ----------------------------------------------------------------------------
00FA68  1               WritePulse1SweepAndControl:     ; $FA68
00FA68  1  A0 7F            ldy #$7F                    ; $FA68: A0 7F
00FA6A  1               ; ----------------------------------------------------------------------------
00FA6A  1               ; Contract:
00FA6A  1               ;   Description: Internal pulse-1 register writer.
00FA6A  1               ;   Entry: Y = sweep value; X = control value.
00FA6A  1               ;   Returns/products: APU $4001/$4000 written.
00FA6A  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00FA6A  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00FA6A  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00FA6A  1               ;          comparison, load, or store path and are not a stable API product.
00FA6A  1               ;   Validation: Internal-entry contract; call sites: internal entry.
00FA6A  1               ; ----------------------------------------------------------------------------
00FA6A  1               WritePulse1SweepAndControlFromRegisters:
00FA6A  1  8C 01 40         sty $4001                   ; $FA6A: 8C 01 40
00FA6D  1               
00FA6D  1               WritePulse1Control:             ; $FA6D
00FA6D  1  8E 00 40         stx $4000                   ; $FA6D: 8E 00 40
00FA70  1  60               rts                         ; $FA70: 60
00FA71  1               
00FA71  1               ; ============================================================================
00FA71  1               ; $FA71-$FA79
00FA71  1               ; Write a caller-supplied pulse 2 control value and reset its sweep state.
00FA71  1               ;
00FA71  1               ; Entry:
00FA71  1               ;   X = value for $4004
00FA71  1               ; ============================================================================
00FA71  1               
00FA71  1               ; ----------------------------------------------------------------------------
00FA71  1               ; Contract:
00FA71  1               ;   Description: Writes Pulse 2 Sweep And Control.
00FA71  1               ;   Entry: Registers: X, Y
00FA71  1               ;   Returns/products: Registers/clobbers: Y
00FA71  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00FA71  1               ;   Memory effects: $4005, $4004
00FA71  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00FA71  1               ;          comparison, load, or store path and are not a stable API product.
00FA71  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00FA71  1               ; ----------------------------------------------------------------------------
00FA71  1               WritePulse2SweepAndControl:     ; $FA71
00FA71  1  A0 7F            ldy #$7F                    ; $FA71: A0 7F
00FA73  1               ; ----------------------------------------------------------------------------
00FA73  1               ; Contract:
00FA73  1               ;   Description: Internal pulse-2 register writer.
00FA73  1               ;   Entry: Y = sweep value; X = control value.
00FA73  1               ;   Returns/products: APU $4005/$4004 written.
00FA73  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00FA73  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00FA73  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00FA73  1               ;          comparison, load, or store path and are not a stable API product.
00FA73  1               ;   Validation: Internal-entry contract; call sites: internal entry.
00FA73  1               ; ----------------------------------------------------------------------------
00FA73  1               WritePulse2SweepAndControlFromRegisters:
00FA73  1  8C 05 40         sty $4005                   ; $FA73: 8C 05 40
00FA76  1               
00FA76  1               WritePulse2Control:             ; $FA76
00FA76  1  8E 04 40         stx $4004                   ; $FA76: 8E 04 40
00FA79  1  60               rts                         ; $FA79: 60
00FA7A  1               
00FA7A  1               ; ============================================================================
00FA7A  1               ; $FA7A-$FA85
00FA7A  1               ; Configure the APU noise channel.
00FA7A  1               ;
00FA7A  1               ; Entry:
00FA7A  1               ;   A = volume and envelope value for $400C
00FA7A  1               ;   X = noise period and mode value for $400E
00FA7A  1               ;
00FA7A  1               ; Operation:
00FA7A  1               ;   The fixed value $08 is written to $400F to reload the noise channel's
00FA7A  1               ;   length counter.
00FA7A  1               ; ============================================================================
00FA7A  1               
00FA7A  1               ; ----------------------------------------------------------------------------
00FA7A  1               ; Contract:
00FA7A  1               ;   Description: Implements Configure Noise Channel.
00FA7A  1               ;   Entry: Registers: A, X, Y
00FA7A  1               ;   Returns/products: Registers/clobbers: Y
00FA7A  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00FA7A  1               ;   Memory effects: $400c, $400e, $400f
00FA7A  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00FA7A  1               ;          comparison, load, or store path and are not a stable API product.
00FA7A  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00FA7A  1               ; ----------------------------------------------------------------------------
00FA7A  1               ConfigureNoiseChannel:          ; $FA7A
00FA7A  1  8D 0C 40         sta $400C                   ; $FA7A: 8D 0C 40
00FA7D  1                                               ; Noise volume and envelope control.
00FA7D  1               
00FA7D  1  8E 0E 40         stx $400E                   ; $FA7D: 8E 0E 40
00FA80  1                                               ; Noise mode and period.
00FA80  1               
00FA80  1  A0 08            ldy #$08                    ; $FA80: A0 08
00FA82  1  8C 0F 40         sty $400F                   ; $FA82: 8C 0F 40
00FA85  1                                               ; Reload the noise length counter.
00FA85  1               
00FA85  1  60               rts                         ; $FA85: 60
00FA86  1               
00FA86  1               ; ============================================================================
00FA86  1               ; $FA86-$FAA2
00FA86  1               ; Save audio state and write a timer period to an APU channel.
00FA86  1               ;
00FA86  1               ; Entry:
00FA86  1               ;   A = period-table index
00FA86  1               ;   X = audio state or duration value
00FA86  1               ;   Y = value saved in $F0
00FA86  1               ;
00FA86  1               ; Behavior:
00FA86  1               ;   1. Save Y in $F0 and X in $F2.
00FA86  1               ;   2. If X is zero, write $7F to pulse 1 sweep through $FA6A.
00FA86  1               ;   3. Load a little-endian timer period from the table at $FA00.
00FA86  1               ;   4. Write the timer low and high bytes to the selected APU channel.
00FA86  1               ;
00FA86  1               ; Default channel:
00FA86  1               ;   X = $00, selecting pulse channel 1 registers $4002/$4003.
00FA86  1               ;
00FA86  1               ; Exit:
00FA86  1               ;   Returns immediately if the selected table high byte is zero.
00FA86  1               ; ============================================================================
00FA86  1               
00FA86  1               WritePulsePeriodFromTable:      ; $FA86
00FA86  1  84 F0            sty $F0                     ; $FA86: 84 F0
00FA88  1                                               ; Save caller-selected audio state.
00FA88  1               
00FA88  1  86 F2            stx $F2                     ; $FA88: 86 F2
00FA8A  1                                               ; Save duration, mode, or countdown state.
00FA8A  1               
00FA8A  1               ; ----------------------------------------------------------------------------
00FA8A  1               ; A nonzero X skips pulse 1 sweep initialization.
00FA8A  1               ; ----------------------------------------------------------------------------
00FA8A  1               
00FA8A  1  D0 03            bne WritePulsePeriod_SelectChannel
00FA8C  1                                               ; $FA8A: D0 03
00FA8C  1               
00FA8C  1               ; ----------------------------------------------------------------------------
00FA8C  1               ; X is zero. Enter the pulse 1 helper at $FA6A, which writes Y=$7F to $4001
00FA8C  1               ; and then falls through to write X to $4000.
00FA8C  1               ;
00FA8C  1               ; This call preserves A, the period-table index.
00FA8C  1               ; ----------------------------------------------------------------------------
00FA8C  1               
00FA8C  1               ; ----------------------------------------------------------------------------
00FA8C  1               ; Contract:
00FA8C  1               ;   Description: Internal period setup after $F0/$F2 were saved.
00FA8C  1               ;   Entry: A = period-table index; X/Y contain saved effect context.
00FA8C  1               ;   Returns/products: Pulse-1 sweep/timer fields initialized.
00FA8C  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00FA8C  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00FA8C  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00FA8C  1               ;          comparison, load, or store path and are not a stable API product.
00FA8C  1               ;   Validation: Internal-entry contract; call sites: internal entry.
00FA8C  1               ; ----------------------------------------------------------------------------
00FA8C  1               InitializePulse1PeriodAfterStateSaved:
00FA8C  1  20 6A FA         jsr WritePulse1SweepAndControlFromRegisters                   ; $FA8C: 20 6A FA
00FA8F  1               
00FA8F  1               ; ----------------------------------------------------------------------------
00FA8F  1               ; Select pulse channel 1 timer registers by default:
00FA8F  1               ;
00FA8F  1               ;   $4002,X = timer low
00FA8F  1               ;   $4003,X = timer high
00FA8F  1               ; ----------------------------------------------------------------------------
00FA8F  1               
00FA8F  1               ; ----------------------------------------------------------------------------
00FA8F  1               ; Contract:
00FA8F  1               ;   Description: Writes Pulse Period  Select Channel.
00FA8F  1               ;   Entry: Registers: A; Memory: $fa01, $fa00
00FA8F  1               ;   Returns/products: Registers/clobbers: A, X, Y
00FA8F  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00FA8F  1               ;   Memory effects: $4002, $4003
00FA8F  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00FA8F  1               ;          comparison, load, or store path and are not a stable API product.
00FA8F  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00FA8F  1               ; ----------------------------------------------------------------------------
00FA8F  1               WritePulsePeriod_SelectChannel: ; $FA8F
00FA8F  1  A2 00            ldx #$00                    ; $FA8F: A2 00
00FA91  1               
00FA91  1               ; ============================================================================
00FA91  1               ; $FA91
00FA91  1               ; Shared timer-table writer.
00FA91  1               ;
00FA91  1               ; Alternate callers enter here with:
00FA91  1               ;
00FA91  1               ;   X=$00 -> pulse 1, $4002/$4003
00FA91  1               ;   X=$04 -> pulse 2, $4006/$4007
00FA91  1               ;   X=$08 -> triangle, $400A/$400B
00FA91  1               ;
00FA91  1               ; Entry:
00FA91  1               ;   A = timer-table index
00FA91  1               ;   X = APU channel register offset
00FA91  1               ; ============================================================================
00FA91  1               
00FA91  1               WriteApuTimerFromTable:         ; $FA91
00FA91  1  A8               tay                         ; $FA91: A8
00FA92  1                                               ; Y = period-table index.
00FA92  1               
00FA92  1               ; ----------------------------------------------------------------------------
00FA92  1               ; Load the timer high byte first.
00FA92  1               ;
00FA92  1               ; The table is stored as little-endian words beginning at $FA00:
00FA92  1               ;
00FA92  1               ;   low byte  = $FA00,Y
00FA92  1               ;   high byte = $FA01,Y
00FA92  1               ; ----------------------------------------------------------------------------
00FA92  1               
00FA92  1  B9 01 FA         lda $FA01,y                 ; $FA92: B9 01 FA
00FA95  1  F0 0B            beq WriteApuTimerFromTable_Return
00FA97  1                                               ; $FA95: F0 0B
00FA97  1                                               ; A zero high byte suppresses the write.
00FA97  1               
00FA97  1  9D 02 40         sta $4002,x                 ; $FA97: 9D 02 40
00FA9A  1                                               ; Write timer low-register address plus X.
00FA9A  1                                               ;
00FA9A  1                                               ; Despite the table naming, this instruction
00FA9A  1                                               ; writes the byte loaded from $FA01,Y first.
00FA9A  1               
00FA9A  1               ; ----------------------------------------------------------------------------
00FA9A  1               ; Load the adjacent table byte, set bit three, and write the timer high or
00FA9A  1               ; length-counter register.
00FA9A  1               ; ----------------------------------------------------------------------------
00FA9A  1               
00FA9A  1  B9 00 FA         lda $FA00,y                 ; $FA9A: B9 00 FA
00FA9D  1  09 08            ora #$08                    ; $FA9D: 09 08
00FA9F  1               
00FA9F  1  9D 03 40         sta $4003,x                 ; $FA9F: 9D 03 40
00FAA2  1               
00FAA2  1               WriteApuTimerFromTable_Return:  ; $FAA2
00FAA2  1  60               rts                         ; $FAA2: 60
00FAA3  1               
00FAA3  1               ; ============================================================================
00FAA3  1               ; $FAA3-$FAA9
00FAA3  1               ; Write a table-selected timer period to pulse channel 2.
00FAA3  1               ;
00FAA3  1               ; $FA73 writes $7F to pulse 2 sweep register $4005. The routine then selects
00FAA3  1               ; register offset $04 and enters the shared timer writer at $FA91.
00FAA3  1               ; ============================================================================
00FAA3  1               
00FAA3  1               WritePulse2PeriodFromTable:     ; $FAA3
00FAA3  1  20 73 FA         jsr WritePulse2SweepAndControlFromRegisters                   ; $FAA3: 20 73 FA
00FAA6  1                                               ; Write $7F to pulse 2 sweep.
00FAA6  1               
00FAA6  1               ; ----------------------------------------------------------------------------
00FAA6  1               ; Contract:
00FAA6  1               ;   Description: Internal pulse-2 timer writer after sweep initialization.
00FAA6  1               ;   Entry: A = timer-table index.
00FAA6  1               ;   Returns/products: APU pulse-2 timer fields written.
00FAA6  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00FAA6  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00FAA6  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00FAA6  1               ;          comparison, load, or store path and are not a stable API product.
00FAA6  1               ;   Validation: Internal-entry contract; call sites: internal entry.
00FAA6  1               ; ----------------------------------------------------------------------------
00FAA6  1               WritePulse2PeriodAfterSweep:
00FAA6  1  A2 04            ldx #$04                    ; $FAA6: A2 04
00FAA8  1                                               ; Select $4006/$4007.
00FAA8  1               
00FAA8  1  D0 E7            bne WriteApuTimerFromTable  ; $FAA8: D0 E7
00FAAA  1                                               ; Always taken.
00FAAA  1               
00FAAA  1               ; ============================================================================
00FAAA  1               ; $FAAA-$FAAD
00FAAA  1               ; Write a table-selected timer period to the triangle channel.
00FAAA  1               ;
00FAAA  1               ; Entry:
00FAAA  1               ;   A = period-table index
00FAAA  1               ; ============================================================================
00FAAA  1               
00FAAA  1               WriteTrianglePeriodFromTable:   ; $FAAA
00FAAA  1  A2 08            ldx #$08                    ; $FAAA: A2 08
00FAAC  1                                               ; Select $400A/$400B.
00FAAC  1               
00FAAC  1  D0 E3            bne WriteApuTimerFromTable  ; $FAAC: D0 E3
00FAAE  1                                               ; Always taken.
00FAAE  1               ; ============================================================================
00FAAE  1               ; $FAAE-$FABF
00FAAE  1               ; Reduce the value in Y by approximately one thirty-second.
00FAAE  1               ;
00FAAE  1               ; Entry:
00FAAE  1               ;   Y = source value
00FAAE  1               ;
00FAAE  1               ; Calculation:
00FAAE  1               ;
00FAAE  1               ;   adjustment = Y >> 5
00FAAE  1               ;
00FAAE  1               ;   if adjustment == 0:
00FAAE  1               ;       adjustment = 1
00FAAE  1               ;
00FAAE  1               ;   A = Y - adjustment
00FAAE  1               ;
00FAAE  1               ; Exit:
00FAAE  1               ;   A = adjusted value
00FAAE  1               ;   Y = original input value
00FAAE  1               ;   $00 = adjustment value
00FAAE  1               ;
00FAAE  1               ; For input values below $20, the routine subtracts one. For values of $20 or
00FAAE  1               ; greater, it subtracts the input divided by 32.
00FAAE  1               ; ============================================================================
00FAAE  1               
00FAAE  1               ReduceValueByOneThirtySecond:   ; $FAAE
00FAAE  1  98               tya                         ; $FAAE: 98
00FAAF  1                                               ; Copy the source value into A.
00FAAF  1               
00FAAF  1               ; ----------------------------------------------------------------------------
00FAAF  1               ; Divide A by 32.
00FAAF  1               ; ----------------------------------------------------------------------------
00FAAF  1               
00FAAF  1  4A               lsr                         ; $FAAF: 4A
00FAB0  1  4A               lsr                         ; $FAB0: 4A
00FAB1  1  4A               lsr                         ; $FAB1: 4A
00FAB2  1  4A               lsr                         ; $FAB2: 4A
00FAB3  1  4A               lsr                         ; $FAB3: 4A
00FAB4  1               
00FAB4  1  85 00            sta $00                     ; $FAB4: 85 00
00FAB6  1                                               ; Save the calculated adjustment.
00FAB6  1               
00FAB6  1               ; ----------------------------------------------------------------------------
00FAB6  1               ; Ensure the adjustment is at least one.
00FAB6  1               ;
00FAB6  1               ; If Y was below $20, shifting right five times produced zero.
00FAB6  1               ; ----------------------------------------------------------------------------
00FAB6  1               
00FAB6  1  D0 02            bne ReduceValueByOneThirtySecond_Subtract
00FAB8  1                                               ; $FAB6: D0 02
00FAB8  1               
00FAB8  1  E6 00            inc $00                     ; $FAB8: E6 00
00FABA  1                                               ; Change zero adjustment to one.
00FABA  1               
00FABA  1               ; ----------------------------------------------------------------------------
00FABA  1               ; Subtract the adjustment from the original input value.
00FABA  1               ; ----------------------------------------------------------------------------
00FABA  1               
00FABA  1               ReduceValueByOneThirtySecond_Subtract: ; $FABA
00FABA  1  98               tya                         ; $FABA: 98
00FABB  1                                               ; Restore the original source value.
00FABB  1               
00FABB  1  38               sec                         ; $FABB: 38
00FABC  1  E5 00            sbc $00                     ; $FABC: E5 00
00FABE  1               
00FABE  1  60               rts                         ; $FABE: 60
00FABF  1               
00FABF  1               ; ============================================================================
00FABF  1               ; $FABF-$FACE
00FABF  1               ; Derive an audio lookup-table index from A and the current audio offset in $F6.
00FABF  1               ;
00FABF  1               ; Entry:
00FABF  1               ;   A = source value
00FABF  1               ;   C = participates in the initial ROR
00FABF  1               ;   $F6 = base audio-table index
00FABF  1               ;
00FABF  1               ; Calculation:
00FABF  1               ;   1. Save the original A in X.
00FABF  1               ;   2. Rotate A right once.
00FABF  1               ;   3. Restore the original A from X.
00FABF  1               ;   4. Rotate left three times.
00FABF  1               ;   5. Keep the low three bits.
00FABF  1               ;   6. Add $F6.
00FABF  1               ;   7. Use the sum to index the table at $FA4A.
00FABF  1               ;
00FABF  1               ; Exit:
00FABF  1               ;   A = selected byte from $FA4A,Y
00FABF  1               ;   X = original input A
00FABF  1               ;   Y = calculated table index
00FABF  1               ; ============================================================================
00FABF  1               
00FABF  1               ; ----------------------------------------------------------------------------
00FABF  1               ; Contract:
00FABF  1               ;   Description: Implements Lookup Audio Control Value.
00FABF  1               ;   Entry: Registers: A, X; Memory: $f6, $fa4a
00FABF  1               ;   Returns/products: Registers/clobbers: A, X, Y; Flags: condition flags may carry result state
00FABF  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00FABF  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00FABF  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00FABF  1               ;          comparison, load, or store path and are not a stable API product.
00FABF  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 2.
00FABF  1               ; ----------------------------------------------------------------------------
00FABF  1               LookupAudioControlValue:        ; $FABF
00FABF  1  AA               tax                         ; $FABF: AA
00FAC0  1                                               ; Preserve the original source value in X.
00FAC0  1               
00FAC0  1  6A               ror                         ; $FAC0: 6A
00FAC1  1                                               ; Rotate the source right through carry.
00FAC1  1                                               ;
00FAC1  1                                               ; The resulting A is not used directly, but
00FAC1  1                                               ; this changes carry for the following ROLs.
00FAC1  1               
00FAC1  1  8A               txa                         ; $FAC1: 8A
00FAC2  1                                               ; Restore the original source value.
00FAC2  1               
00FAC2  1               ; ----------------------------------------------------------------------------
00FAC2  1               ; Rotate the original value left three times through the carry established by
00FAC2  1               ; the preceding ROR.
00FAC2  1               ; ----------------------------------------------------------------------------
00FAC2  1               
00FAC2  1  2A               rol                         ; $FAC2: 2A
00FAC3  1  2A               rol                         ; $FAC3: 2A
00FAC4  1  2A               rol                         ; $FAC4: 2A
00FAC5  1               
00FAC5  1               ; ----------------------------------------------------------------------------
00FAC5  1               ; Contract:
00FAC5  1               ;   Description: Internal lookup entry after carry and source value are prepared.
00FAC5  1               ;   Entry: A/X and carry encode lookup offset; $F6 is base index.
00FAC5  1               ;   Returns/products: A = selected control value; X preserves source; Y = table index.
00FAC5  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00FAC5  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00FAC5  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00FAC5  1               ;          comparison, load, or store path and are not a stable API product.
00FAC5  1               ;   Validation: Internal-entry contract; call sites: internal entry.
00FAC5  1               ; ----------------------------------------------------------------------------
00FAC5  1               LookupAudioControlValueFinalRotate:
00FAC5  1  29 07            and #$07                    ; $FAC5: 29 07
00FAC7  1                                               ; Keep a three-bit table offset.
00FAC7  1               
00FAC7  1  18               clc                         ; $FAC7: 18
00FAC8  1  65 F6            adc $F6                     ; $FAC8: 65 F6
00FACA  1                                               ; Add the current audio-table base.
00FACA  1               
00FACA  1  A8               tay                         ; $FACA: A8
00FACB  1               
00FACB  1  B9 4A FA         lda $FA4A,y                 ; $FACB: B9 4A FA
00FACE  1                                               ; Load the selected audio control value.
00FACE  1               
00FACE  1  60               rts                         ; $FACE: 60
00FACF  1               
00FACF  1               ; ============================================================================
00FACF  1               ; $FACF-$FAD9
00FACF  1               ; Configure the first sound-effect preset.
00FACF  1               ;
00FACF  1               ; Preset values:
00FACF  1               ;   X = $17
00FACF  1               ;   A = $12
00FACF  1               ;   Y = $84
00FACF  1               ;
00FACF  1               ; The common setup helper at $FA86 saves Y in $F0 and X in $F2, then writes an
00FACF  1               ; APU timer value selected by A.
00FACF  1               ; ============================================================================
00FACF  1               
00FACF  1               StartPulse1EffectPreset1:        ; $FACF
00FACF  1  A2 17            ldx #$17                    ; $FACF: A2 17
00FAD1  1                                               ; Duration or audio-state value.
00FAD1  1               
00FAD1  1  A9 12            lda #$12                    ; $FAD1: A9 12
00FAD3  1                                               ; Timer-table index.
00FAD3  1               
00FAD3  1  20 86 FA         jsr WritePulsePeriodFromTable
00FAD6  1                                               ; $FAD3: 20 86 FA
00FAD6  1               
00FAD6  1               ; ----------------------------------------------------------------------------
00FAD6  1               ; Contract:
00FAD6  1               ;   Description: Internal preset-1 continuation with timer state initialized.
00FAD6  1               ;   Entry: Y initialized to preset control $84.
00FAD6  1               ;   Returns/products: Continues shared pulse-1 preset update.
00FAD6  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00FAD6  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00FAD6  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00FAD6  1               ;          comparison, load, or store path and are not a stable API product.
00FAD6  1               ;   Validation: Internal-entry contract; call sites: internal entry.
00FAD6  1               ; ----------------------------------------------------------------------------
00FAD6  1               StartPulse1EffectPreset1FromControl:
00FAD6  1  A0 84            ldy #$84                    ; $FAD6: A0 84
00FAD8  1                                               ; Default control or envelope value.
00FAD8  1               
00FAD8  1  D0 14            bne UpdatePulse1PresetEffect
00FADA  1                                               ; $FAD8: D0 14
00FADA  1                                               ; Always taken.
00FADA  1                                               ; Target $FAEE.
00FADA  1               
00FADA  1               ; ============================================================================
00FADA  1               ; $FADA-$FAE4
00FADA  1               ; Configure the second sound-effect preset.
00FADA  1               ;
00FADA  1               ; Preset values:
00FADA  1               ;   X = $1E
00FADA  1               ;   A = $0C
00FADA  1               ;   Y = $85
00FADA  1               ; ============================================================================
00FADA  1               
00FADA  1               StartPulse1EffectPreset2:        ; $FADA
00FADA  1  A2 1E            ldx #$1E                    ; $FADA: A2 1E
00FADC  1               
00FADC  1  A9 0C            lda #$0C                    ; $FADC: A9 0C
00FADE  1               
00FADE  1  20 86 FA         jsr WritePulsePeriodFromTable
00FAE1  1                                               ; $FADE: 20 86 FA
00FAE1  1               
00FAE1  1               ; ----------------------------------------------------------------------------
00FAE1  1               ; Contract:
00FAE1  1               ;   Description: Internal preset-2 continuation with timer state initialized.
00FAE1  1               ;   Entry: Y initialized to preset control $85.
00FAE1  1               ;   Returns/products: Continues shared pulse-1 preset update.
00FAE1  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00FAE1  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00FAE1  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00FAE1  1               ;          comparison, load, or store path and are not a stable API product.
00FAE1  1               ;   Validation: Internal-entry contract; call sites: internal entry.
00FAE1  1               ; ----------------------------------------------------------------------------
00FAE1  1               StartPulse1EffectPreset2FromControl:
00FAE1  1  A0 85            ldy #$85                    ; $FAE1: A0 85
00FAE3  1               
00FAE3  1  D0 09            bne UpdatePulse1PresetEffect
00FAE5  1                                               ; $FAE3: D0 09
00FAE5  1                                               ; Always taken.
00FAE5  1                                               ; Target $FAEE.
00FAE5  1               
00FAE5  1               ; ============================================================================
00FAE5  1               ; $FAE5-$FAED
00FAE5  1               ; Configure the third sound-effect preset.
00FAE5  1               ;
00FAE5  1               ; Preset values:
00FAE5  1               ;   X = $27
00FAE5  1               ;   A = $06
00FAE5  1               ;   Y = $86
00FAE5  1               ;
00FAE5  1               ; This entry falls directly into the shared finalization path.
00FAE5  1               ; ============================================================================
00FAE5  1               
00FAE5  1               StartPulse1EffectPreset3:        ; $FAE5
00FAE5  1  A2 27            ldx #$27                    ; $FAE5: A2 27
00FAE7  1               
00FAE7  1  A9 06            lda #$06                    ; $FAE7: A9 06
00FAE9  1               
00FAE9  1  20 86 FA         jsr WritePulsePeriodFromTable
00FAEC  1                                               ; $FAE9: 20 86 FA
00FAEC  1               
00FAEC  1               ; ----------------------------------------------------------------------------
00FAEC  1               ; Contract:
00FAEC  1               ;   Description: Internal preset-3 continuation with timer state initialized.
00FAEC  1               ;   Entry: Y initialized to preset control $86.
00FAEC  1               ;   Returns/products: Continues shared pulse-1 preset update.
00FAEC  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00FAEC  1               ;   Memory effects: See symbolic operands in the routine body; zero-page scratch roles are documented locally.
00FAEC  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00FAEC  1               ;          comparison, load, or store path and are not a stable API product.
00FAEC  1               ;   Validation: Internal-entry contract; call sites: internal entry.
00FAEC  1               ; ----------------------------------------------------------------------------
00FAEC  1               StartPulse1EffectPreset3FromControl:
00FAEC  1  A0 86            ldy #$86                    ; $FAEC: A0 86
00FAEE  1               
00FAEE  1               ; ============================================================================
00FAEE  1               ; $FAEE-$FB04
00FAEE  1               ; Finalize one of the three sound-effect presets.
00FAEE  1               ;
00FAEE  1               ; The routine selects an alternate Y value when bit three of $00 is set,
00FAEE  1               ; derives a second control value in X from $F2, then tail-jumps to $FB5A.
00FAEE  1               ;
00FAEE  1               ; Entry:
00FAEE  1               ;   Y = preset-specific control value
00FAEE  1               ;   $F2 = duration or sound-state value saved by $FA86
00FAEE  1               ; ============================================================================
00FAEE  1               
00FAEE  1               UpdatePulse1PresetEffect:      ; $FAEE
00FAEE  1  A5 00            lda $00                     ; $FAEE: A5 00
00FAF0  1               
00FAF0  1  29 08            and #$08                    ; $FAF0: 29 08
00FAF2  1  F0 02            beq FinalizeSoundEffectPreset_SelectX
00FAF4  1                                               ; $FAF2: F0 02
00FAF4  1               
00FAF4  1               ; ----------------------------------------------------------------------------
00FAF4  1               ; When bit three of $00 is set, replace the preset-specific Y value with $8D.
00FAF4  1               ; ----------------------------------------------------------------------------
00FAF4  1               
00FAF4  1  A0 8D            ldy #$8D                    ; $FAF4: A0 8D
00FAF6  1               
00FAF6  1               ; ----------------------------------------------------------------------------
00FAF6  1               ; Select the initial channel/control value.
00FAF6  1               ; ----------------------------------------------------------------------------
00FAF6  1               
00FAF6  1               FinalizeSoundEffectPreset_SelectX: ; $FAF6
00FAF6  1  A2 5A            ldx #$5A                    ; $FAF6: A2 5A
00FAF8  1               
00FAF8  1               ; ----------------------------------------------------------------------------
00FAF8  1               ; For $F2 values below $14, derive X from half the value and force bits six and
00FAF8  1               ; four through OR #$50.
00FAF8  1               ;
00FAF8  1               ; For $F2 values $14 or greater, retain X=$5A.
00FAF8  1               ; ----------------------------------------------------------------------------
00FAF8  1               
00FAF8  1  A5 F2            lda $F2                     ; $FAF8: A5 F2
00FAFA  1               
00FAFA  1  C9 14            cmp #$14                    ; $FAFA: C9 14
00FAFC  1  B0 04            bcs FinalizeSoundEffectPreset_Apply
00FAFE  1                                               ; $FAFC: B0 04
00FAFE  1               
00FAFE  1  4A               lsr                         ; $FAFE: 4A
00FAFF  1  09 50            ora #$50                    ; $FAFF: 09 50
00FB01  1  AA               tax                         ; $FB01: AA
00FB02  1               
00FB02  1               ; ----------------------------------------------------------------------------
00FB02  1               ; Tail-call the shared sound-effect register updater.
00FB02  1               ;
00FB02  1               ; Entry to $FB5A:
00FB02  1               ;   X = calculated control value
00FB02  1               ;   Y = preset or alternate envelope value
00FB02  1               ; ----------------------------------------------------------------------------
00FB02  1               
00FB02  1               FinalizeSoundEffectPreset_Apply: ; $FB02
00FB02  1  4C 5A FB         jmp UpdateAudioEffect1_Write                   ; $FB02: 4C 5A FB
00FB05  1               
00FB05  1               ; ============================================================================
00FB05  1               ; $FB05-$FB42
00FB05  1               ; Main audio-update dispatcher.
00FB05  1               ;
00FB05  1               ; Audio state:
00FB05  1               ;   $FF = pending sound-effect flags
00FB05  1               ;   $F0 = active sound-effect state
00FB05  1               ;   $F2 = effect countdown or phase
00FB05  1               ;   $F3 = effect-specific state
00FB05  1               ;   $FA = audio lock or override state
00FB05  1               ;
00FB05  1               ; The dispatcher alternates between bits in $F0 and $FF. Each carry-producing
00FB05  1               ; shift routes to a different sound-effect setup or update handler.
00FB05  1               ; ============================================================================
00FB05  1               
00FB05  1               ; ----------------------------------------------------------------------------
00FB05  1               ; Contract:
00FB05  1               ;   Description: Updates Audio Engine.
00FB05  1               ;   Entry: Registers: A, Y; Memory: $ff, $f0, $fa
00FB05  1               ;   Returns/products: Registers/clobbers: A, X, Y
00FB05  1               ;   Clobbers: A, X, Y, and processor flags as indicated by the instructions below.
00FB05  1               ;   Memory effects: $00, $f0, $f2, $f3
00FB05  1               ;   Flags: Unless explicitly described, flags reflect the final arithmetic,
00FB05  1               ;          comparison, load, or store path and are not a stable API product.
00FB05  1               ;   Validation: Inferred from annotated instructions and call sites; call sites: 1.
00FB05  1               ; ----------------------------------------------------------------------------
00FB05  1               UpdateAudioEngine:              ; $FB05
00FB05  1  A4 FF            ldy RenderStateFlags                     ; $FB05: A4 FF
00FB07  1  84 00            sty $00                     ; $FB07: 84 00
00FB09  1                                               ; Preserve the original pending-effect flags.
00FB09  1               
00FB09  1  A5 F0            lda $F0                     ; $FB09: A5 F0
00FB0B  1                                               ; Active-effect flags or state.
00FB0B  1               
00FB0B  1  A6 FA            ldx $FA                     ; $FB0B: A6 FA
00FB0D  1  D0 31            bne UpdateAudioEngine_Finalize
00FB0F  1                                               ; $FB0D: D0 31
00FB0F  1                                               ; An override or lock skips effect selection.
00FB0F  1               
00FB0F  1               ; ----------------------------------------------------------------------------
00FB0F  1               ; Test active-effect bit zero.
00FB0F  1               ;
00FB0F  1               ; Carry set transfers directly into the first preset's finalization path at
00FB0F  1               ; $FAD6, where Y is initialized to $84.
00FB0F  1               ; ----------------------------------------------------------------------------
00FB0F  1               
00FB0F  1  4A               lsr                         ; $FB0F: 4A
00FB10  1  B0 C4            bcs StartPulse1EffectPreset1FromControl                   ; $FB10: B0 C4
00FB12  1               
00FB12  1               ; ----------------------------------------------------------------------------
00FB12  1               ; Test pending-effect bit zero.
00FB12  1               ; ----------------------------------------------------------------------------
00FB12  1               
00FB12  1  46 FF            lsr RenderStateFlags                     ; $FB12: 46 FF
00FB14  1  B0 B9            bcs StartPulse1EffectPreset1 ; $FB14: B0 B9
00FB16  1               
00FB16  1               ; ----------------------------------------------------------------------------
00FB16  1               ; Test active-effect bit one.
00FB16  1               ;
00FB16  1               ; Target $FAE1 initializes Y=$85 for the second preset.
00FB16  1               ; ----------------------------------------------------------------------------
00FB16  1               
00FB16  1  4A               lsr                         ; $FB16: 4A
00FB17  1  B0 C8            bcs StartPulse1EffectPreset2FromControl                   ; $FB17: B0 C8
00FB19  1               
00FB19  1               ; ----------------------------------------------------------------------------
00FB19  1               ; Test pending-effect bit one.
00FB19  1               ; ----------------------------------------------------------------------------
00FB19  1               
00FB19  1  46 FF            lsr RenderStateFlags                     ; $FB19: 46 FF
00FB1B  1  B0 BD            bcs StartPulse1EffectPreset2 ; $FB1B: B0 BD
00FB1D  1               
00FB1D  1               ; ----------------------------------------------------------------------------
00FB1D  1               ; Test active-effect bit two.
00FB1D  1               ;
00FB1D  1               ; Target $FAEC initializes Y=$86 for the third preset.
00FB1D  1               ; ----------------------------------------------------------------------------
00FB1D  1               
00FB1D  1  4A               lsr                         ; $FB1D: 4A
00FB1E  1  B0 CC            bcs StartPulse1EffectPreset3FromControl                   ; $FB1E: B0 CC
00FB20  1               
00FB20  1               ; ----------------------------------------------------------------------------
00FB20  1               ; Test pending-effect bit two.
00FB20  1               ; ----------------------------------------------------------------------------
00FB20  1               
00FB20  1  46 FF            lsr RenderStateFlags                     ; $FB20: 46 FF
00FB22  1  B0 C1            bcs StartPulse1EffectPreset3 ; $FB22: B0 C1
00FB24  1               
00FB24  1               ; ----------------------------------------------------------------------------
00FB24  1               ; Discard the next active and pending bits.
00FB24  1               ; ----------------------------------------------------------------------------
00FB24  1               
00FB24  1  4A               lsr                         ; $FB24: 4A
00FB25  1  46 FF            lsr RenderStateFlags                     ; $FB25: 46 FF
00FB27  1               
00FB27  1               ; ----------------------------------------------------------------------------
00FB27  1               ; Test the next active-effect bit.
00FB27  1               ; ----------------------------------------------------------------------------
00FB27  1               
00FB27  1  4A               lsr                         ; $FB27: 4A
00FB28  1  B0 20            bcs UpdatePulse1DescendingEffect      ; $FB28: B0 20
00FB2A  1                                               ; Target $FB4A.
00FB2A  1               
00FB2A  1               ; ----------------------------------------------------------------------------
00FB2A  1               ; Test the corresponding pending-effect bit.
00FB2A  1               ; ----------------------------------------------------------------------------
00FB2A  1               
00FB2A  1  46 FF            lsr RenderStateFlags                     ; $FB2A: 46 FF
00FB2C  1  B0 15            bcs StartPulse1DescendingEffect       ; $FB2C: B0 15
00FB2E  1                                               ; Target $FB43.
00FB2E  1               
00FB2E  1               ; ----------------------------------------------------------------------------
00FB2E  1               ; Test the next active-effect bit.
00FB2E  1               ; ----------------------------------------------------------------------------
00FB2E  1               
00FB2E  1  4A               lsr                         ; $FB2E: 4A
00FB2F  1  B0 3A            bcs UpdatePulse1StateChangeEffect      ; $FB2F: B0 3A
00FB31  1                                               ; Target $FB6B.
00FB31  1               
00FB31  1               ; ----------------------------------------------------------------------------
00FB31  1               ; Test the corresponding pending-effect bit.
00FB31  1               ; ----------------------------------------------------------------------------
00FB31  1               
00FB31  1  46 FF            lsr RenderStateFlags                     ; $FB31: 46 FF
00FB33  1  B0 2E            bcs StartPulse1StateChangeEffect       ; $FB33: B0 2E
00FB35  1                                               ; Target $FB63.
00FB35  1               
00FB35  1               ; ----------------------------------------------------------------------------
00FB35  1               ; No recognized effect remains.
00FB35  1               ;
00FB35  1               ; Reset pulse channel 1 and clear the primary effect state.
00FB35  1               ; ----------------------------------------------------------------------------
00FB35  1               
00FB35  1               ClearPrimaryAudioEffect:        ; $FB35
00FB35  1  20 60 FA         jsr ConfigurePulse1ControlPreset
00FB38  1                                               ; $FB35: 20 60 FA
00FB38  1               
00FB38  1  A9 00            lda #$00                    ; $FB38: A9 00
00FB3A  1  85 F0            sta $F0                     ; $FB3A: 85 F0
00FB3C  1  85 F2            sta $F2                     ; $FB3C: 85 F2
00FB3E  1  85 F3            sta $F3                     ; $FB3E: 85 F3
00FB40  1               
00FB40  1               ; ----------------------------------------------------------------------------
00FB40  1               ; Continue to the common audio finalization path at $FBFF.
00FB40  1               ; ----------------------------------------------------------------------------
00FB40  1               
00FB40  1               UpdateAudioEngine_Finalize:     ; $FB40
00FB40  1  4C FF FB         jmp UpdateSecondaryEffects                   ; $FB40: 4C FF FB
00FB43  1               
00FB43  1               ; ============================================================================
00FB43  1               ; $FB43-$FB49
00FB43  1               ; Start audio effect 1.
00FB43  1               ;
00FB43  1               ; Preset:
00FB43  1               ;   X = $14
00FB43  1               ;   A = $26
00FB43  1               ;
00FB43  1               ; The period helper stores X in $F2 and writes the selected pulse period.
00FB43  1               ; Execution then falls through to the effect-update path at $FB4A.
00FB43  1               ; ============================================================================
00FB43  1               
00FB43  1               StartPulse1DescendingEffect:              ; $FB43
00FB43  1  A2 14            ldx #$14                    ; $FB43: A2 14
00FB45  1  A9 26            lda #$26                    ; $FB45: A9 26
00FB47  1               
00FB47  1  20 86 FA         jsr WritePulsePeriodFromTable
00FB4A  1                                               ; $FB47: 20 86 FA
00FB4A  1               
00FB4A  1               ; ============================================================================
00FB4A  1               ; $FB4A-$FB62
00FB4A  1               ; Update audio effect 1.
00FB4A  1               ;
00FB4A  1               ; The effect changes pulse channel 1 control as $F2 counts down. Values below
00FB4A  1               ; $10 derive the control register dynamically; larger values use preset $98.
00FB4A  1               ; ============================================================================
00FB4A  1               
00FB4A  1               UpdatePulse1DescendingEffect:             ; $FB4A
00FB4A  1  A2 98            ldx #$98                    ; $FB4A: A2 98
00FB4C  1                                               ; Default pulse control.
00FB4C  1               
00FB4C  1  A0 84            ldy #$84                    ; $FB4C: A0 84
00FB4E  1                                               ; Default sweep or effect state.
00FB4E  1               
00FB4E  1  A5 F2            lda $F2                     ; $FB4E: A5 F2
00FB50  1  C9 10            cmp #$10                    ; $FB50: C9 10
00FB52  1  B0 06            bcs UpdateAudioEffect1_Write
00FB54  1                                               ; $FB52: B0 06
00FB54  1               
00FB54  1               ; ----------------------------------------------------------------------------
00FB54  1               ; Final effect phase.
00FB54  1               ;
00FB54  1               ; Use alternate state $8D and derive the control byte from half the countdown.
00FB54  1               ; ----------------------------------------------------------------------------
00FB54  1               
00FB54  1  A0 8D            ldy #$8D                    ; $FB54: A0 8D
00FB56  1               
00FB56  1  4A               lsr                         ; $FB56: 4A
00FB57  1  09 90            ora #$90                    ; $FB57: 09 90
00FB59  1  AA               tax                         ; $FB59: AA
00FB5A  1               
00FB5A  1               ; ----------------------------------------------------------------------------
00FB5A  1               ; Write pulse channel 1 sweep and control.
00FB5A  1               ; ----------------------------------------------------------------------------
00FB5A  1               
00FB5A  1               UpdateAudioEffect1_Write:       ; $FB5A
00FB5A  1  20 6A FA         jsr WritePulse1SweepAndControlFromRegisters                   ; $FB5A: 20 6A FA
00FB5D  1                                               ; Write Y to $4001 and X to $4000.
00FB5D  1               
00FB5D  1               ; ----------------------------------------------------------------------------
00FB5D  1               ; Count the effect down.
00FB5D  1               ;
00FB5D  1               ; When it expires, clear the primary effect state at $FB35. Otherwise continue
00FB5D  1               ; through the common audio finalizer at $FB40.
00FB5D  1               ; ----------------------------------------------------------------------------
00FB5D  1               
00FB5D  1  C6 F2            dec $F2                     ; $FB5D: C6 F2
00FB5F  1  F0 D4            beq ClearPrimaryAudioEffect ; $FB5F: F0 D4
00FB61  1               
00FB61  1  D0 DD            bne UpdateAudioEngine_Finalize
00FB63  1                                               ; $FB61: D0 DD
00FB63  1                                               ; Always taken while $F2 is nonzero.
00FB63  1               
00FB63  1               ; ============================================================================
00FB63  1               ; $FB63-$FB6A
00FB63  1               ; Start audio effect 2.
00FB63  1               ;
00FB63  1               ; The caller reached this path because the corresponding pending-effect bit was
00FB63  1               ; set. Y still contains the original pending flags loaded at $FB05.
00FB63  1               ; ============================================================================
00FB63  1               
00FB63  1               StartPulse1StateChangeEffect:              ; $FB63
00FB63  1  84 F0            sty $F0                     ; $FB63: 84 F0
00FB65  1                                               ; Save the active effect state.
00FB65  1               
00FB65  1  A0 9D            ldy #$9D                    ; $FB65: A0 9D
00FB67  1                                               ; Initial pulse sweep/control value.
00FB67  1               
00FB67  1  A9 30            lda #$30                    ; $FB67: A9 30
00FB69  1                                               ; Initial timer or pitch value.
00FB69  1               
00FB69  1  D0 2C            bne UpdateAudioEffect2_Trigger
00FB6B  1                                               ; $FB69: D0 2C
00FB6B  1                                               ; Always taken to $FB97.
00FB6B  1               
00FB6B  1               ; ============================================================================
00FB6B  1               ; $FB6B-$FBA0
00FB6B  1               ; Update audio effect 2.
00FB6B  1               ;
00FB6B  1               ; This handler uses bit six of the original pending flags, the countdown in
00FB6B  1               ; $F2, and the previous state in $F3 to choose pulse control and pitch values.
00FB6B  1               ; ============================================================================
00FB6B  1               
00FB6B  1               UpdatePulse1StateChangeEffect:             ; $FB6B
00FB6B  1  46 FF            lsr RenderStateFlags                     ; $FB6B: 46 FF
00FB6D  1               
00FB6D  1  90 C6            bcc ClearPrimaryAudioEffect ; $FB6D: 90 C6
00FB6F  1                                               ; End the effect when the shifted bit is clear.
00FB6F  1               
00FB6F  1               ; ----------------------------------------------------------------------------
00FB6F  1               ; Test bit six of the original pending-effect flags saved at $00.
00FB6F  1               ; ----------------------------------------------------------------------------
00FB6F  1               
00FB6F  1  A5 00            lda $00                     ; $FB6F: A5 00
00FB71  1  29 40            and #$40                    ; $FB71: 29 40
00FB73  1  D0 0A            bne UpdateAudioEffect2_CheckState
00FB75  1                                               ; $FB73: D0 0A
00FB75  1               
00FB75  1               ; ----------------------------------------------------------------------------
00FB75  1               ; Without bit six set, wait until the countdown reaches exactly $C0.
00FB75  1               ; ----------------------------------------------------------------------------
00FB75  1               
00FB75  1  A5 F2            lda $F2                     ; $FB75: A5 F2
00FB77  1  C9 C0            cmp #$C0                    ; $FB77: C9 C0
00FB79  1  D0 21            bne UpdateAudioEffect2_CountDown
00FB7B  1                                               ; $FB79: D0 21
00FB7B  1               
00FB7B  1  A0 9E            ldy #$9E                    ; $FB7B: A0 9E
00FB7D  1               
00FB7D  1  D0 11            bne UpdateAudioEffect2_WriteSweep
00FB7F  1                                               ; $FB7D: D0 11
00FB7F  1               
00FB7F  1               ; ----------------------------------------------------------------------------
00FB7F  1               ; Bit six is set. Toggle or compare the saved effect state in $F3.
00FB7F  1               ; ----------------------------------------------------------------------------
00FB7F  1               
00FB7F  1               UpdateAudioEffect2_CheckState:  ; $FB7F
00FB7F  1  A4 F3            ldy $F3                     ; $FB7F: A4 F3
00FB81  1               
00FB81  1  85 F3            sta $F3                     ; $FB81: 85 F3
00FB83  1                                               ; Save A=$40 in $F3.
00FB83  1               
00FB83  1  98               tya                         ; $FB83: 98
00FB84  1  45 F3            eor $F3                     ; $FB84: 45 F3
00FB86  1  F0 14            beq UpdateAudioEffect2_CountDown
00FB88  1                                               ; $FB86: F0 14
00FB88  1               
00FB88  1               ; ----------------------------------------------------------------------------
00FB88  1               ; The state changed. Use sweep/control value $A5.
00FB88  1               ; ----------------------------------------------------------------------------
00FB88  1               
00FB88  1  A0 A5            ldy #$A5                    ; $FB88: A0 A5
00FB8A  1               
00FB8A  1  A5 F2            lda $F2                     ; $FB8A: A5 F2
00FB8C  1  C9 A8            cmp #$A8                    ; $FB8C: C9 A8
00FB8E  1  90 05            bcc UpdateAudioEffect2_SelectPitch
00FB90  1                                               ; $FB8E: 90 05
00FB90  1               
00FB90  1               ; ----------------------------------------------------------------------------
00FB90  1               ; For countdown values at least $A8, write the selected sweep value directly.
00FB90  1               ; ----------------------------------------------------------------------------
00FB90  1               
00FB90  1               UpdateAudioEffect2_WriteSweep:  ; $FB90
00FB90  1  8C 01 40         sty $4001                   ; $FB90: 8C 01 40
00FB93  1               
00FB93  1  D0 07            bne UpdateAudioEffect2_CountDown
00FB95  1                                               ; $FB93: D0 07
00FB95  1                                               ; Expected to be taken because the selected Y
00FB95  1                                               ; values are nonzero.
00FB95  1               
00FB95  1               ; ----------------------------------------------------------------------------
00FB95  1               ; Select pitch value $48 and channel control $B3.
00FB95  1               ; ----------------------------------------------------------------------------
00FB95  1               
00FB95  1               UpdateAudioEffect2_SelectPitch: ; $FB95
00FB95  1  A9 48            lda #$48                    ; $FB95: A9 48
00FB97  1               
00FB97  1               UpdateAudioEffect2_Trigger:     ; $FB97
00FB97  1  A2 B3            ldx #$B3                    ; $FB97: A2 B3
00FB99  1               
00FB99  1  20 8C FA         jsr InitializePulse1PeriodAfterStateSaved                   ; $FB99: 20 8C FA
00FB9C  1                                               ; Initialize pulse period/control using A and X.
00FB9C  1               
00FB9C  1               ; ----------------------------------------------------------------------------
00FB9C  1               ; Decrement the effect timer, then continue through the later audio sequencer
00FB9C  1               ; at $FC94.
00FB9C  1               ; ----------------------------------------------------------------------------
00FB9C  1               
00FB9C  1               UpdateAudioEffect2_CountDown:   ; $FB9C
00FB9C  1  C6 F2            dec $F2                     ; $FB9C: C6 F2
00FB9E  1               
00FB9E  1  4C 94 FC         jmp UpdateMusicSequencer                   ; $FB9E: 4C 94 FC
00FBA1  1               
00FBA1  1               ; ============================================================================
00FBA1  1               ; $FBA1-$FBD2
00FBA1  1               ; Pulse effect controlled by the phase counter in $F4.
00FBA1  1               ; ============================================================================
00FBA1  1               
00FBA1  1               StartPulse2PhaseEffect:             ; $FBA1
00FBA1  1  84 F1            sty $F1                     ; $FBA1: 84 F1
00FBA3  1               
00FBA3  1  A9 20            lda #$20                    ; $FBA3: A9 20
00FBA5  1  85 F4            sta $F4                     ; $FBA5: 85 F4
00FBA7  1               
00FBA7  1  D0 06            bne PulseEffectF4_Phase18   ; $FBA7: D0 06
00FBA9  1               
00FBA9  1               UpdatePulse2PhaseEffect:            ; $FBA9
00FBA9  1  A5 F4            lda $F4                     ; $FBA9: A5 F4
00FBAB  1               
00FBAB  1  C9 18            cmp #$18                    ; $FBAB: C9 18
00FBAD  1  D0 04            bne PulseEffectF4_Phase10   ; $FBAD: D0 04
00FBAF  1               
00FBAF  1               PulseEffectF4_Phase18:          ; $FBAF
00FBAF  1  A9 08            lda #$08                    ; $FBAF: A9 08
00FBB1  1  D0 06            bne PulseEffectF4_WriteTimer
00FBB3  1                                               ; $FBB1: D0 06
00FBB3  1               
00FBB3  1               PulseEffectF4_Phase10:          ; $FBB3
00FBB3  1  C9 10            cmp #$10                    ; $FBB3: C9 10
00FBB5  1  D0 05            bne PulseEffectF4_Configure ; $FBB5: D0 05
00FBB7  1               
00FBB7  1  A9 2E            lda #$2E                    ; $FBB7: A9 2E
00FBB9  1               
00FBB9  1               PulseEffectF4_WriteTimer:       ; $FBB9
00FBB9  1  20 A6 FA         jsr WritePulse2PeriodAfterSweep                   ; $FBB9: 20 A6 FA
00FBBC  1               
00FBBC  1               PulseEffectF4_Configure:        ; $FBBC
00FBBC  1  A2 9D            ldx #$9D                    ; $FBBC: A2 9D
00FBBE  1  A0 83            ldy #$83                    ; $FBBE: A0 83
00FBC0  1               
00FBC0  1  A5 F4            lda $F4                     ; $FBC0: A5 F4
00FBC2  1               
00FBC2  1  C9 0C            cmp #$0C                    ; $FBC2: C9 0C
00FBC4  1  B0 02            bcs PulseEffectF4_CheckUpper
00FBC6  1                                               ; $FBC4: B0 02
00FBC6  1               
00FBC6  1  A0 84            ldy #$84                    ; $FBC6: A0 84
00FBC8  1               
00FBC8  1               PulseEffectF4_CheckUpper:       ; $FBC8
00FBC8  1  C9 1A            cmp #$1A                    ; $FBC8: C9 1A
00FBCA  1  B0 04            bcs PulseEffectF4_Apply     ; $FBCA: B0 04
00FBCC  1               
00FBCC  1  4A               lsr                         ; $FBCC: 4A
00FBCD  1  09 90            ora #$90                    ; $FBCD: 09 90
00FBCF  1  AA               tax                         ; $FBCF: AA
00FBD0  1               
00FBD0  1               PulseEffectF4_Apply:            ; $FBD0
00FBD0  1  4C 55 FC         jmp WritePulse2PhaseRegisters
00FBD3  1                                               ; $FBD0: 4C 55 FC
00FBD3  1               
00FBD3  1               ; ============================================================================
00FBD3  1               ; $FBD3-$FBFE
00FBD3  1               ; Alternate pulse effect using the same shared register writer.
00FBD3  1               ; ============================================================================
00FBD3  1               
00FBD3  1               StartAlternatePulse2PhaseEffect:    ; $FBD3
00FBD3  1  84 F1            sty $F1                     ; $FBD3: 84 F1
00FBD5  1               
00FBD5  1  A9 1C            lda #$1C                    ; $FBD5: A9 1C
00FBD7  1  85 F4            sta $F4                     ; $FBD7: 85 F4
00FBD9  1               
00FBD9  1  A9 12            lda #$12                    ; $FBD9: A9 12
00FBDB  1  A2 98            ldx #$98                    ; $FBDB: A2 98
00FBDD  1  A0 96            ldy #$96                    ; $FBDD: A0 96
00FBDF  1               
00FBDF  1  20 A3 FA         jsr WritePulse2PeriodFromTable
00FBE2  1                                               ; $FBDF: 20 A3 FA
00FBE2  1               
00FBE2  1  D0 74            bne CountDownPulse2PhaseEffect ; $FBE2: D0 74
00FBE4  1               
00FBE4  1               UpdateAlternatePulse2PhaseEffect:   ; $FBE4
00FBE4  1  A2 9C            ldx #$9C                    ; $FBE4: A2 9C
00FBE6  1  A0 96            ldy #$96                    ; $FBE6: A0 96
00FBE8  1               
00FBE8  1  A5 F4            lda $F4                     ; $FBE8: A5 F4
00FBEA  1  C9 18            cmp #$18                    ; $FBEA: C9 18
00FBEC  1  B0 0A            bcs PulseEffectAlternate_TestOdd
00FBEE  1                                               ; $FBEC: B0 0A
00FBEE  1               
00FBEE  1  A0 86            ldy #$86                    ; $FBEE: A0 86
00FBF0  1               
00FBF0  1  4A               lsr                         ; $FBF0: 4A
00FBF1  1  B0 08            bcs PulseEffectAlternate_Use90
00FBF3  1                                               ; $FBF1: B0 08
00FBF3  1               
00FBF3  1  09 90            ora #$90                    ; $FBF3: 09 90
00FBF5  1  AA               tax                         ; $FBF5: AA
00FBF6  1               
00FBF6  1  D0 5D            bne WritePulse2PhaseRegisters
00FBF8  1                                               ; $FBF6: D0 5D
00FBF8  1               
00FBF8  1               PulseEffectAlternate_TestOdd:   ; $FBF8
00FBF8  1  4A               lsr                         ; $FBF8: 4A
00FBF9  1  90 5A            bcc WritePulse2PhaseRegisters
00FBFB  1                                               ; $FBF9: 90 5A
00FBFB  1               
00FBFB  1               PulseEffectAlternate_Use90:     ; $FBFB
00FBFB  1  A2 90            ldx #$90                    ; $FBFB: A2 90
00FBFD  1  D0 56            bne WritePulse2PhaseRegisters
00FBFF  1                                               ; $FBFD: D0 56
00FBFF  1               
00FBFF  1               ; ============================================================================
00FBFF  1               ; $FBFF-$FC1D
00FBFF  1               ; Secondary audio-effect dispatcher.
00FBFF  1               ; ============================================================================
00FBFF  1               
00FBFF  1               UpdateSecondaryEffects:     ; $FBFF
00FBFF  1  A4 FE            ldy PendingAudioFlags                     ; $FBFF: A4 FE
00FC01  1  84 00            sty $00                     ; $FC01: 84 00
00FC03  1               
00FC03  1  A5 F1            lda $F1                     ; $FC03: A5 F1
00FC05  1               
00FC05  1  A6 FB            ldx $FB                     ; $FC05: A6 FB
00FC07  1  D0 57            bne DispatchMusicAndNoise ; $FC07: D0 57
00FC09  1               
00FC09  1  4A               lsr                         ; $FC09: 4A
00FC0A  1  B0 9D            bcs UpdatePulse2PhaseEffect     ; $FC0A: B0 9D
00FC0C  1               
00FC0C  1  46 FE            lsr PendingAudioFlags                     ; $FC0C: 46 FE
00FC0E  1  B0 91            bcs StartPulse2PhaseEffect      ; $FC0E: B0 91
00FC10  1               
00FC10  1  4A               lsr                         ; $FC10: 4A
00FC11  1  B0 D1            bcs UpdateAlternatePulse2PhaseEffect
00FC13  1                                               ; $FC11: B0 D1
00FC13  1               
00FC13  1  46 FE            lsr PendingAudioFlags                     ; $FC13: 46 FE
00FC15  1  B0 BC            bcs StartAlternatePulse2PhaseEffect
00FC17  1                                               ; $FC15: B0 BC
00FC17  1               
00FC17  1  4A               lsr                         ; $FC17: 4A
00FC18  1  B0 19            bcs UpdateTrianglePitchSweep
00FC1A  1                                               ; $FC18: B0 19
00FC1A  1               
00FC1A  1  46 FE            lsr PendingAudioFlags                     ; $FC1A: 46 FE
00FC1C  1  90 42            bcc DispatchMusicAndNoise ; $FC1C: 90 42
00FC1E  1               
00FC1E  1               ; ============================================================================
00FC1E  1               ; $FC1E-$FC32
00FC1E  1               ; Start the triangle sweep effect.
00FC1E  1               ; ============================================================================
00FC1E  1               
00FC1E  1               StartTrianglePitchSweep:       ; $FC1E
00FC1E  1  84 F1            sty $F1                     ; $FC1E: 84 F1
00FC20  1               
00FC20  1  A9 05            lda #$05                    ; $FC20: A9 05
00FC22  1  85 F4            sta $F4                     ; $FC22: 85 F4
00FC24  1               
00FC24  1  A2 3F            ldx #$3F                    ; $FC24: A2 3F
00FC26  1               
00FC26  1  EE FD 07         inc $07FD                   ; $FC26: EE FD 07
00FC29  1               
00FC29  1  AD FD 07         lda $07FD                   ; $FC29: AD FD 07
00FC2C  1  4A               lsr                         ; $FC2C: 4A
00FC2D  1  90 02            bcc StartTriangleSweep_Save ; $FC2D: 90 02
00FC2F  1               
00FC2F  1  A2 50            ldx #$50                    ; $FC2F: A2 50
00FC31  1               
00FC31  1               StartTriangleSweep_Save:        ; $FC31
00FC31  1  86 F5            stx $F5                     ; $FC31: 86 F5
00FC33  1               
00FC33  1               ; ============================================================================
00FC33  1               ; $FC33-$FC5F
00FC33  1               ; Update the triangle sweep and shared pulse registers.
00FC33  1               ; ============================================================================
00FC33  1               
00FC33  1               UpdateTrianglePitchSweep:      ; $FC33
00FC33  1  A5 F5            lda $F5                     ; $FC33: A5 F5
00FC35  1               
00FC35  1  4A               lsr                         ; $FC35: 4A
00FC36  1  4A               lsr                         ; $FC36: 4A
00FC37  1  4A               lsr                         ; $FC37: 4A
00FC38  1               
00FC38  1  65 F5            adc $F5                     ; $FC38: 65 F5
00FC3A  1  85 F5            sta $F5                     ; $FC3A: 85 F5
00FC3C  1               
00FC3C  1  0A               asl                         ; $FC3C: 0A
00FC3D  1  0A               asl                         ; $FC3D: 0A
00FC3E  1  8D 06 40         sta $4006                   ; $FC3E: 8D 06 40
00FC41  1               
00FC41  1  2A               rol                         ; $FC41: 2A
00FC42  1  29 03            and #$03                    ; $FC42: 29 03
00FC44  1  8D 07 40         sta $4007                   ; $FC44: 8D 07 40
00FC47  1               
00FC47  1  A0 81            ldy #$81                    ; $FC47: A0 81
00FC49  1  A2 50            ldx #$50                    ; $FC49: A2 50
00FC4B  1               
00FC4B  1  A5 F4            lda $F4                     ; $FC4B: A5 F4
00FC4D  1  C9 04            cmp #$04                    ; $FC4D: C9 04
00FC4F  1  90 04            bcc WritePulse2PhaseRegisters
00FC51  1                                               ; $FC4F: 90 04
00FC51  1               
00FC51  1  18               clc                         ; $FC51: 18
00FC52  1  69 4F            adc #$4F                    ; $FC52: 69 4F
00FC54  1  AA               tax                         ; $FC54: AA
00FC55  1               
00FC55  1               WritePulse2PhaseRegisters:   ; $FC55
00FC55  1  20 73 FA         jsr WritePulse2SweepAndControlFromRegisters                   ; $FC55: 20 73 FA
00FC58  1               
00FC58  1               CountDownPulse2PhaseEffect:        ; $FC58
00FC58  1  C6 F4            dec $F4                     ; $FC58: C6 F4
00FC5A  1  D0 04            bne DispatchMusicAndNoise ; $FC5A: D0 04
00FC5C  1               
00FC5C  1  A9 00            lda #$00                    ; $FC5C: A9 00
00FC5E  1  85 F1            sta $F1                     ; $FC5E: 85 F1
00FC60  1               
00FC60  1               ; ============================================================================
00FC60  1               ; $FC60-$FC99
00FC60  1               ; Dispatch miscellaneous audio events.
00FC60  1               ; ============================================================================
00FC60  1               
00FC60  1               DispatchMusicAndNoise:        ; $FC60
00FC60  1  A5 EF            lda GameplaySuspended                     ; $FC60: A5 EF
00FC62  1  D0 30            bne UpdateMusicSequencer    ; $FC62: D0 30
00FC64  1               
00FC64  1  A4 00            ldy $00                     ; $FC64: A4 00
00FC66  1  30 2F            bmi UpdateNoiseEffectSequence    ; $FC66: 30 2F
00FC68  1               
00FC68  1  AD F5 07         lda $07F5                   ; $FC68: AD F5 07
00FC6B  1               
00FC6B  1  0A               asl                         ; $FC6B: 0A
00FC6C  1  30 3A            bmi UpdateDmcOutputEffect            ; $FC6C: 30 3A
00FC6E  1               
00FC6E  1  06 00            asl $00                     ; $FC6E: 06 00
00FC70  1  30 28            bmi StartTriangleEffectShort            ; $FC70: 30 28
00FC72  1               
00FC72  1  0A               asl                         ; $FC72: 0A
00FC73  1  30 5A            bmi ContinueTimedAudioEffect            ; $FC73: 30 5A
00FC75  1               
00FC75  1  06 00            asl $00                     ; $FC75: 06 00
00FC77  1  30 3B            bmi StartTriangleEffectMedium            ; $FC77: 30 3B
00FC79  1               
00FC79  1  0A               asl                         ; $FC79: 0A
00FC7A  1  30 68            bmi UpdateTriangleEffectLong            ; $FC7A: 30 68
00FC7C  1               
00FC7C  1  06 00            asl $00                     ; $FC7C: 06 00
00FC7E  1  30 56            bmi StartTriangleEffectLong            ; $FC7E: 30 56
00FC80  1               
00FC80  1  0A               asl                         ; $FC80: 0A
00FC81  1  30 7E            bmi UpdateTriangleEffectAlternate            ; $FC81: 30 7E
00FC83  1               
00FC83  1  06 00            asl $00                     ; $FC83: 06 00
00FC85  1  30 6C            bmi StartTriangleEffectAlternate            ; $FC85: 30 6C
00FC87  1               
00FC87  1               ResetTimedAudioEvents:              ; $FC87
00FC87  1  A9 00            lda #$00                    ; $FC87: A9 00
00FC89  1               
00FC89  1  8D FA 07         sta $07FA                   ; $FC89: 8D FA 07
00FC8C  1  8D F5 07         sta $07F5                   ; $FC8C: 8D F5 07
00FC8F  1               
00FC8F  1  A9 10            lda #$10                    ; $FC8F: A9 10
00FC91  1  8D 0C 40         sta $400C                   ; $FC91: 8D 0C 40
00FC94  1               
00FC94  1               UpdateMusicSequencer:           ; $FC94
00FC94  1  4C 2A FD         jmp UpdateMusicEngine                   ; $FC94: 4C 2A FD
00FC97  1               
00FC97  1               UpdateNoiseEffectSequence:           ; $FC97
00FC97  1  4C 14 FD         jmp UpdateNoiseEnvelopeSequence                   ; $FC97: 4C 14 FD
00FC9A  1               
00FC9A  1               ; ============================================================================
00FC9A  1               ; $FC9A-$FCA7
00FC9A  1               ; Audio event 2.
00FC9A  1               ; ============================================================================
00FC9A  1               
00FC9A  1               StartTriangleEffectShort:                   ; $FC9A
00FC9A  1  8C F5 07         sty $07F5                   ; $FC9A: 8C F5 07
00FC9D  1               
00FC9D  1  A9 09            lda #$09                    ; $FC9D: A9 09
00FC9F  1  8D F8 07         sta $07F8                   ; $FC9F: 8D F8 07
00FCA2  1               
00FCA2  1  A9 35            lda #$35                    ; $FCA2: A9 35
00FCA4  1  A0 1C            ldy #$1C                    ; $FCA4: A0 1C
00FCA6  1               
00FCA6  1  D0 18            bne ConfigureTimedTriangleEffect  ; $FCA6: D0 18
00FCA8  1               
00FCA8  1               ; ============================================================================
00FCA8  1               ; $FCA8-$FCB3
00FCA8  1               ; Audio event 1.
00FCA8  1               ; ============================================================================
00FCA8  1               
00FCA8  1               UpdateDmcOutputEffect:                   ; $FCA8
00FCA8  1  AD FF 07         lda $07FF                   ; $FCA8: AD FF 07
00FCAB  1               
00FCAB  1  18               clc                         ; $FCAB: 18
00FCAC  1  69 10            adc #$10                    ; $FCAC: 69 10
00FCAE  1  8D FF 07         sta $07FF                   ; $FCAE: 8D FF 07
00FCB1  1               
00FCB1  1  4C CF FC         jmp CountDownTimedAudioEffect    ; $FCB1: 4C CF FC
00FCB4  1               
00FCB4  1               ; ============================================================================
00FCB4  1               ; $FCB4-$FCD5
00FCB4  1               ; Audio event 4 and shared triangle-channel configuration.
00FCB4  1               ; ============================================================================
00FCB4  1               
00FCB4  1               StartTriangleEffectMedium:                   ; $FCB4
00FCB4  1  8C F5 07         sty $07F5                   ; $FCB4: 8C F5 07
00FCB7  1               
00FCB7  1  A9 08            lda #$08                    ; $FCB7: A9 08
00FCB9  1  8D F8 07         sta $07F8                   ; $FCB9: 8D F8 07
00FCBC  1               
00FCBC  1  A9 54            lda #$54                    ; $FCBC: A9 54
00FCBE  1  A0 0A            ldy #$0A                    ; $FCBE: A0 0A
00FCC0  1               
00FCC0  1               ConfigureTimedTriangleEffect:         ; $FCC0
00FCC0  1  8D 0A 40         sta $400A                   ; $FCC0: 8D 0A 40
00FCC3  1               
00FCC3  1  A2 08            ldx #$08                    ; $FCC3: A2 08
00FCC5  1  8E 0B 40         stx $400B                   ; $FCC5: 8E 0B 40
00FCC8  1               
00FCC8  1  8C 08 40         sty $4008                   ; $FCC8: 8C 08 40
00FCCB  1               
00FCCB  1  A9 00            lda #$00                    ; $FCCB: A9 00
00FCCD  1  85 F0            sta $F0                     ; $FCCD: 85 F0
00FCCF  1               
00FCCF  1               CountDownTimedAudioEffect:           ; $FCCF
00FCCF  1  CE F8 07         dec $07F8                   ; $FCCF: CE F8 07
00FCD2  1  F0 B3            beq ResetTimedAudioEvents       ; $FCD2: F0 B3
00FCD4  1               
00FCD4  1  D0 BE            bne UpdateMusicSequencer    ; $FCD4: D0 BE
00FCD6  1               
00FCD6  1               ; ============================================================================
00FCD6  1               ; $FCD6-$FCE3
00FCD6  1               ; Initialize audio event 6.
00FCD6  1               ;
00FCD6  1               ; This event:
00FCD6  1               ;   - saves the current event flags in $07F5
00FCD6  1               ;   - initializes a countdown of $12 in $07F8
00FCD6  1               ;   - selects triangle linear-counter value $06
00FCD6  1               ;   - selects timer value $3F
00FCD6  1               ;   - enters the shared triangle-channel configuration at $FCC0
00FCD6  1               ; ============================================================================
00FCD6  1               
00FCD6  1               StartTriangleEffectLong:                   ; $FCD6
00FCD6  1  8C F5 07         sty $07F5                   ; $FCD6: 8C F5 07
00FCD9  1                                               ; Preserve the active event flags.
00FCD9  1               
00FCD9  1  A9 12            lda #$12                    ; $FCD9: A9 12
00FCDB  1  8D F8 07         sta $07F8                   ; $FCDB: 8D F8 07
00FCDE  1                                               ; Initialize the event countdown.
00FCDE  1               
00FCDE  1  A0 06            ldy #$06                    ; $FCDE: A0 06
00FCE0  1                                               ; Triangle linear-counter value.
00FCE0  1               
00FCE0  1  A9 3F            lda #$3F                    ; $FCE0: A9 3F
00FCE2  1                                               ; Triangle timer-low value.
00FCE2  1               
00FCE2  1  D0 DC            bne ConfigureTimedTriangleEffect  ; $FCE2: D0 DC
00FCE4  1                                               ; Always taken.
00FCE4  1                                               ; Target $FCC0.
00FCE4  1               
00FCE4  1               ; ============================================================================
00FCE4  1               ; $FCE4-$FCF2
00FCE4  1               ; Update audio event 5.
00FCE4  1               ;
00FCE4  1               ; The handler modifies the triangle-channel parameters at two countdown
00FCE4  1               ; thresholds:
00FCE4  1               ;
00FCE4  1               ;   $07F8 = $0E:
00FCE4  1               ;       use timer $3F and linear-counter value $06
00FCE4  1               ;
00FCE4  1               ;   $07F8 = $0A:
00FCE4  1               ;       use timer $3F and linear-counter value $20
00FCE4  1               ;
00FCE4  1               ; Other countdown values continue through the common countdown path at $FCCF.
00FCE4  1               ; ============================================================================
00FCE4  1               
00FCE4  1               UpdateTriangleEffectLong:                   ; $FCE4
00FCE4  1  AD F8 07         lda $07F8                   ; $FCE4: AD F8 07
00FCE7  1               
00FCE7  1  C9 0E            cmp #$0E                    ; $FCE7: C9 0E
00FCE9  1  F0 F3            beq AudioEvent_6_Configure  ; $FCE9: F0 F3
00FCEB  1                                               ; Target $FCDE.
00FCEB  1               
00FCEB  1  C9 0A            cmp #$0A                    ; $FCEB: C9 0A
00FCED  1  D0 E0            bne CountDownTimedAudioEffect    ; $FCED: D0 E0
00FCEF  1                                               ; Target $FCCF.
00FCEF  1               
00FCEF  1               ; ----------------------------------------------------------------------------
00FCEF  1               ; At countdown $0A, use a larger triangle linear-counter value.
00FCEF  1               ; ----------------------------------------------------------------------------
00FCEF  1               
00FCEF  1  A0 20            ldy #$20                    ; $FCEF: A0 20
00FCF1  1               
00FCF1  1  D0 ED            bne AudioEvent_5_SetTimer   ; $FCF1: D0 ED
00FCF3  1                                               ; Always taken.
00FCF3  1                                               ; Target $FCE0.
00FCF3  1               
00FCF3  1               ; ----------------------------------------------------------------------------
00FCF3  1               ; Internal entry shared with StartTriangleEffectLong.
00FCF3  1               ; ----------------------------------------------------------------------------
00FCF3  1               
00FCF3  1               AudioEvent_6_Configure = $FCDE
00FCF3  1               AudioEvent_5_SetTimer  = $FCE0
00FCF3  1               
00FCF3  1               ; ============================================================================
00FCF3  1               ; $FCF3-$FD00
00FCF3  1               ; Initialize audio event 8.
00FCF3  1               ;
00FCF3  1               ; This event:
00FCF3  1               ;   - saves the current event flags
00FCF3  1               ;   - initializes a countdown of $14
00FCF3  1               ;   - selects triangle linear-counter value $18
00FCF3  1               ;   - selects timer value $6A
00FCF3  1               ;   - enters the shared triangle-channel configuration at $FCC0
00FCF3  1               ; ============================================================================
00FCF3  1               
00FCF3  1               StartTriangleEffectAlternate:                   ; $FCF3
00FCF3  1  8C F5 07         sty $07F5                   ; $FCF3: 8C F5 07
00FCF6  1               
00FCF6  1  A9 14            lda #$14                    ; $FCF6: A9 14
00FCF8  1  8D F8 07         sta $07F8                   ; $FCF8: 8D F8 07
00FCFB  1               
00FCFB  1  A0 18            ldy #$18                    ; $FCFB: A0 18
00FCFD  1               
00FCFD  1               AudioEvent_8_SetTimer:          ; $FCFD
00FCFD  1  A9 6A            lda #$6A                    ; $FCFD: A9 6A
00FCFF  1               
00FCFF  1  D0 BF            bne ConfigureTimedTriangleEffect  ; $FCFF: D0 BF
00FD01  1                                               ; Always taken.
00FD01  1                                               ; Target $FCC0.
00FD01  1               
00FD01  1               ; ============================================================================
00FD01  1               ; $FD01-$FD0B
00FD01  1               ; Update audio event 7.
00FD01  1               ;
00FD01  1               ; At countdown value $08, the triangle linear-counter value changes to $10
00FD01  1               ; while retaining timer value $6A.
00FD01  1               ;
00FD01  1               ; All other countdown values use the common countdown path at $FCCF.
00FD01  1               ; ============================================================================
00FD01  1               
00FD01  1               UpdateTriangleEffectAlternate:                   ; $FD01
00FD01  1  AD F8 07         lda $07F8                   ; $FD01: AD F8 07
00FD04  1               
00FD04  1  C9 08            cmp #$08                    ; $FD04: C9 08
00FD06  1  D0 C7            bne CountDownTimedAudioEffect    ; $FD06: D0 C7
00FD08  1                                               ; Target $FCCF.
00FD08  1               
00FD08  1  A0 10            ldy #$10                    ; $FD08: A0 10
00FD0A  1               
00FD0A  1  D0 F1            bne AudioEvent_8_SetTimer   ; $FD0A: D0 F1
00FD0C  1                                               ; Always taken.
00FD0C  1                                               ; Target $FCFD.
00FD0C  1               
00FD0C  1               ; ============================================================================
00FD0C  1               ; Existing target definition.
00FD0C  1               ;
00FD0C  1               ; ContinueTimedAudioEffect is the shared countdown path itself. The dispatcher branch at
00FD0C  1               ; $FC73 intentionally enters at $FCCF.
00FD0C  1               ; ============================================================================
00FD0C  1               
00FD0C  1               ContinueTimedAudioEffect = CountDownTimedAudioEffect
00FD0C  1               
00FD0C  1               ; ============================================================================
00FD0C  1               ; $FD0C-$FD13
00FD0C  1               ; Eight-entry audio lookup table.
00FD0C  1               ;
00FD0C  1               ; The routine beginning at $FD14 derives a three-bit index and uses it to load
00FD0C  1               ; one of these values.
00FD0C  1               ; ============================================================================
00FD0C  1               
00FD0C  1               NoiseEnvelopeSequence:        ; $FD0C
00FD0C  1  12 13 14 15      .byte $12,$13,$14,$15
00FD10  1  15 14 13 13      .byte $15,$14,$13,$13
00FD14  1               
00FD14  1               ; ============================================================================
00FD14  1               ; $FD14-$FD29
00FD14  1               ; Update a table-driven noise or effect value from the sequence counter $07FA.
00FD14  1               ;
00FD14  1               ; The high five bits of $07FA select one of eight entries in the table at
00FD14  1               ; $FD0C. The selected value is passed to ConfigureNoiseChannel at $FA7A with
00FD14  1               ; X=$0E.
00FD14  1               ;
00FD14  1               ; Exit:
00FD14  1               ;   $07FA incremented
00FD14  1               ; ============================================================================
00FD14  1               
00FD14  1               UpdateNoiseEnvelopeSequence:            ; $FD14
00FD14  1  AD FA 07         lda $07FA                   ; $FD14: AD FA 07
00FD17  1               
00FD17  1  4A               lsr                         ; $FD17: 4A
00FD18  1  4A               lsr                         ; $FD18: 4A
00FD19  1  4A               lsr                         ; $FD19: 4A
00FD1A  1  4A               lsr                         ; $FD1A: 4A
00FD1B  1  4A               lsr                         ; $FD1B: 4A
00FD1C  1               
00FD1C  1  29 07            and #$07                    ; $FD1C: 29 07
00FD1E  1  A8               tay                         ; $FD1E: A8
00FD1F  1               
00FD1F  1  B9 0C FD         lda NoiseEnvelopeSequence,y
00FD22  1                                               ; $FD1F: B9 0C FD
00FD22  1               
00FD22  1  A2 0E            ldx #$0E                    ; $FD22: A2 0E
00FD24  1               
00FD24  1  20 7A FA         jsr ConfigureNoiseChannel   ; $FD24: 20 7A FA
00FD27  1               
00FD27  1  EE FA 07         inc $07FA                   ; $FD27: EE FA 07
00FD2A  1               
00FD2A  1               ; ============================================================================
00FD2A  1               ; $FD2A-$FD66
00FD2A  1               ; Initialize a music or note-sequence stream when required.
00FD2A  1               ;
00FD2A  1               ; State:
00FD2A  1               ;   $FD      = sequence request or selector
00FD2A  1               ;   $FC      = selected sequence bank
00FD2A  1               ;   $FA/$FB  = channel stream cursors
00FD2A  1               ;   $F6-$FA  = five-byte stream descriptor loaded from the table at $FE40
00FD2A  1               ;   $07F0-$07F2 = per-channel countdowns
00FD2A  1               ; ============================================================================
00FD2A  1               
00FD2A  1               UpdateMusicEngine:            ; $FD2A
00FD2A  1  A5 FD            lda $FD                     ; $FD2A: A5 FD
00FD2C  1  D0 06            bne StartMusicSequence ; $FD2C: D0 06
00FD2E  1               
00FD2E  1  AD F4 07         lda $07F4                   ; $FD2E: AD F4 07
00FD31  1  D0 34            bne UpdatePulse1MusicChannel     ; $FD31: D0 34
00FD33  1               
00FD33  1  60               rts                         ; $FD33: 60
00FD34  1               
00FD34  1               ; ----------------------------------------------------------------------------
00FD34  1               ; Convert the sequence selector in A into a bank index in Y.
00FD34  1               ;
00FD34  1               ; The loop shifts A left until carry becomes set, decrementing Y for each
00FD34  1               ; unsuccessful shift.
00FD34  1               ; ----------------------------------------------------------------------------
00FD34  1               
00FD34  1               StartMusicSequence:        ; $FD34
00FD34  1  A0 07            ldy #$07                    ; $FD34: A0 07
00FD36  1               
00FD36  1               InitializeMusicSequence_FindBank: ; $FD36
00FD36  1  0A               asl                         ; $FD36: 0A
00FD37  1  B0 03            bcs InitializeMusicSequence_BankFound
00FD39  1                                               ; $FD37: B0 03
00FD39  1               
00FD39  1  88               dey                         ; $FD39: 88
00FD3A  1  D0 FA            bne InitializeMusicSequence_FindBank
00FD3C  1                                               ; $FD3A: D0 FA
00FD3C  1               
00FD3C  1               ; ----------------------------------------------------------------------------
00FD3C  1               ; Mark that a sequence is active and save the selected bank.
00FD3C  1               ; ----------------------------------------------------------------------------
00FD3C  1               
00FD3C  1               InitializeMusicSequence_BankFound: ; $FD3C
00FD3C  1  EE F4 07         inc $07F4                   ; $FD3C: EE F4 07
00FD3F  1               
00FD3F  1  84 FC            sty $FC                     ; $FD3F: 84 FC
00FD41  1               
00FD41  1               ; ----------------------------------------------------------------------------
00FD41  1               ; Bank one is remapped to bank zero.
00FD41  1               ; ----------------------------------------------------------------------------
00FD41  1               
00FD41  1  C0 01            cpy #$01                    ; $FD41: C0 01
00FD43  1  D0 04            bne InitializeMusicSequence_LoadPointer
00FD45  1                                               ; $FD43: D0 04
00FD45  1               
00FD45  1  A9 00            lda #$00                    ; $FD45: A9 00
00FD47  1  85 FC            sta $FC                     ; $FD47: 85 FC
00FD49  1               
00FD49  1               ; ----------------------------------------------------------------------------
00FD49  1               ; The table at $FE40 contains an outer pointer/index byte followed by a five-byte
00FD49  1               ; stream descriptor. The first lookup maps the selected bank to the descriptor
00FD49  1               ; offset.
00FD49  1               ; ----------------------------------------------------------------------------
00FD49  1               
00FD49  1               InitializeMusicSequence_LoadPointer: ; $FD49
00FD49  1  B9 40 FE         lda $FE40,y                 ; $FD49: B9 40 FE
00FD4C  1  A8               tay                         ; $FD4C: A8
00FD4D  1               
00FD4D  1  A2 00            ldx #$00                    ; $FD4D: A2 00
00FD4F  1  86 FB            stx $FB                     ; $FD4F: 86 FB
00FD51  1               
00FD51  1               ; ----------------------------------------------------------------------------
00FD51  1               ; Copy five bytes from the selected descriptor into $F6-$FA.
00FD51  1               ; ----------------------------------------------------------------------------
00FD51  1               
00FD51  1               InitializeMusicSequence_CopyDescriptor: ; $FD51
00FD51  1  B9 40 FE         lda $FE40,y                 ; $FD51: B9 40 FE
00FD54  1  95 F6            sta $F6,x                   ; $FD54: 95 F6
00FD56  1               
00FD56  1  C8               iny                         ; $FD56: C8
00FD57  1  E8               inx                         ; $FD57: E8
00FD58  1               
00FD58  1  E0 05            cpx #$05                    ; $FD58: E0 05
00FD5A  1  D0 F5            bne InitializeMusicSequence_CopyDescriptor
00FD5C  1                                               ; $FD5A: D0 F5
00FD5C  1               
00FD5C  1               ; ----------------------------------------------------------------------------
00FD5C  1               ; Initialize all three channel countdowns to one so each channel fetches its
00FD5C  1               ; first command immediately.
00FD5C  1               ; ----------------------------------------------------------------------------
00FD5C  1               
00FD5C  1  A9 01            lda #$01                    ; $FD5C: A9 01
00FD5E  1               
00FD5E  1  8D F0 07         sta $07F0                   ; $FD5E: 8D F0 07
00FD61  1  8D F1 07         sta $07F1                   ; $FD61: 8D F1 07
00FD64  1  8D F2 07         sta $07F2                   ; $FD64: 8D F2 07
00FD67  1               
00FD67  1               ; ============================================================================
00FD67  1               ; $FD67-$FDB8
00FD67  1               ; Update the first music channel.
00FD67  1               ;
00FD67  1               ; $FA is the channel stream cursor. $07F1 is its countdown.
00FD67  1               ; ============================================================================
00FD67  1               
00FD67  1               UpdatePulse1MusicChannel:            ; $FD67
00FD67  1  A4 FA            ldy $FA                     ; $FD67: A4 FA
00FD69  1  F0 4E            beq UpdatePulse2MusicChannel     ; $FD69: F0 4E
00FD6B  1               
00FD6B  1               ; ----------------------------------------------------------------------------
00FD6B  1               ; For sequence bank zero, reset pulse 1 when the countdown reaches two.
00FD6B  1               ; ----------------------------------------------------------------------------
00FD6B  1               
00FD6B  1  A5 FC            lda $FC                     ; $FD6B: A5 FC
00FD6D  1  D0 0A            bne UpdateMusicChannel1_Decrement
00FD6F  1                                               ; $FD6D: D0 0A
00FD6F  1               
00FD6F  1  AD F1 07         lda $07F1                   ; $FD6F: AD F1 07
00FD72  1  C9 02            cmp #$02                    ; $FD72: C9 02
00FD74  1  D0 03            bne UpdateMusicChannel1_Decrement
00FD76  1                                               ; $FD74: D0 03
00FD76  1               
00FD76  1  20 60 FA         jsr ConfigurePulse1ControlPreset
00FD79  1                                               ; $FD76: 20 60 FA
00FD79  1               
00FD79  1               ; ----------------------------------------------------------------------------
00FD79  1               ; Count down the current note duration.
00FD79  1               ; ----------------------------------------------------------------------------
00FD79  1               
00FD79  1               UpdateMusicChannel1_Decrement:  ; $FD79
00FD79  1  CE F1 07         dec $07F1                   ; $FD79: CE F1 07
00FD7C  1  D0 3B            bne UpdatePulse2MusicChannel     ; $FD7C: D0 3B
00FD7E  1               
00FD7E  1               ; ----------------------------------------------------------------------------
00FD7E  1               ; Fetch the next stream command.
00FD7E  1               ; ----------------------------------------------------------------------------
00FD7E  1               
00FD7E  1  E6 FA            inc $FA                     ; $FD7E: E6 FA
00FD80  1               
00FD80  1  B1 F7            lda ($F7),y                 ; $FD80: B1 F7
00FD82  1  10 0C            bpl UpdateMusicChannel1_HaveNote
00FD84  1                                               ; $FD82: 10 0C
00FD84  1               
00FD84  1               ; ----------------------------------------------------------------------------
00FD84  1               ; Negative bytes are extended commands. Decode the duration/control value and
00FD84  1               ; fetch the following note byte.
00FD84  1               ; ----------------------------------------------------------------------------
00FD84  1               
00FD84  1  20 C5 FA         jsr LookupAudioControlValueFinalRotate                   ; $FD84: 20 C5 FA
00FD87  1  8D F3 07         sta $07F3                   ; $FD87: 8D F3 07
00FD8A  1               
00FD8A  1  A4 FA            ldy $FA                     ; $FD8A: A4 FA
00FD8C  1  E6 FA            inc $FA                     ; $FD8C: E6 FA
00FD8E  1               
00FD8E  1  B1 F7            lda ($F7),y                 ; $FD8E: B1 F7
00FD90  1               
00FD90  1               ; ----------------------------------------------------------------------------
00FD90  1               ; Convert the note value through the audio period helper at $FA8F.
00FD90  1               ; ----------------------------------------------------------------------------
00FD90  1               
00FD90  1               UpdateMusicChannel1_HaveNote:   ; $FD90
00FD90  1  20 8F FA         jsr WritePulsePeriod_SelectChannel                   ; $FD90: 20 8F FA
00FD93  1               
00FD93  1  D0 04            bne UpdateMusicChannel1_SelectControl
00FD95  1                                               ; $FD93: D0 04
00FD95  1               
00FD95  1  A2 10            ldx #$10                    ; $FD95: A2 10
00FD97  1  D0 17            bne UpdateMusicChannel1_Write
00FD99  1                                               ; $FD97: D0 17
00FD99  1               
00FD99  1               ; ----------------------------------------------------------------------------
00FD99  1               ; Select pulse control according to sequence bank, duration, and channel state.
00FD99  1               ; ----------------------------------------------------------------------------
00FD99  1               
00FD99  1               UpdateMusicChannel1_SelectControl: ; $FD99
00FD99  1  A2 5A            ldx #$5A                    ; $FD99: A2 5A
00FD9B  1               
00FD9B  1  A5 FC            lda $FC                     ; $FD9B: A5 FC
00FD9D  1  F0 11            beq UpdateMusicChannel1_Write
00FD9F  1                                               ; $FD9D: F0 11
00FD9F  1               
00FD9F  1  A2 46            ldx #$46                    ; $FD9F: A2 46
00FDA1  1               
00FDA1  1  AD F3 07         lda $07F3                   ; $FDA1: AD F3 07
00FDA4  1  C9 08            cmp #$08                    ; $FDA4: C9 08
00FDA6  1  B0 02            bcs UpdateMusicChannel1_CheckAlt
00FDA8  1                                               ; $FDA6: B0 02
00FDA8  1               
00FDA8  1  A2 42            ldx #$42                    ; $FDA8: A2 42
00FDAA  1               
00FDAA  1               UpdateMusicChannel1_CheckAlt:   ; $FDAA
00FDAA  1  A5 F9            lda $F9                     ; $FDAA: A5 F9
00FDAC  1  D0 02            bne UpdateMusicChannel1_Write
00FDAE  1                                               ; $FDAC: D0 02
00FDAE  1               
00FDAE  1  A2 86            ldx #$86                    ; $FDAE: A2 86
00FDB0  1               
00FDB0  1               ; ----------------------------------------------------------------------------
00FDB0  1               ; Write pulse channel 1 sweep/control and reload the note countdown.
00FDB0  1               ; ----------------------------------------------------------------------------
00FDB0  1               
00FDB0  1               UpdateMusicChannel1_Write:      ; $FDB0
00FDB0  1  20 68 FA         jsr WritePulse1SweepAndControl                   ; $FDB0: 20 68 FA
00FDB3  1               
00FDB3  1  AD F3 07         lda $07F3                   ; $FDB3: AD F3 07
00FDB6  1  8D F1 07         sta $07F1                   ; $FDB6: 8D F1 07
00FDB9  1               
00FDB9  1               ; ============================================================================
00FDB9  1               ; $FDB9-$FE04
00FDB9  1               ; Update the second music channel.
00FDB9  1               ;
00FDB9  1               ; $FB is the channel stream cursor. $07F0 is its countdown.
00FDB9  1               ; ============================================================================
00FDB9  1               
00FDB9  1               UpdatePulse2MusicChannel:            ; $FDB9
00FDB9  1  A5 FC            lda $FC                     ; $FDB9: A5 FC
00FDBB  1  D0 0A            bne UpdateMusicChannel2_Decrement
00FDBD  1                                               ; $FDBB: D0 0A
00FDBD  1               
00FDBD  1  AD F0 07         lda $07F0                   ; $FDBD: AD F0 07
00FDC0  1  C9 02            cmp #$02                    ; $FDC0: C9 02
00FDC2  1  D0 03            bne UpdateMusicChannel2_Decrement
00FDC4  1                                               ; $FDC2: D0 03
00FDC4  1               
00FDC4  1  20 64 FA         jsr ConfigurePulse2ControlPreset
00FDC7  1                                               ; $FDC4: 20 64 FA
00FDC7  1               
00FDC7  1               UpdateMusicChannel2_Decrement:  ; $FDC7
00FDC7  1  CE F0 07         dec $07F0                   ; $FDC7: CE F0 07
00FDCA  1  D0 39            bne UpdateTriangleMusicChannel     ; $FDCA: D0 39
00FDCC  1               
00FDCC  1               ; ----------------------------------------------------------------------------
00FDCC  1               ; Fetch the next byte from the second channel stream.
00FDCC  1               ; ----------------------------------------------------------------------------
00FDCC  1               
00FDCC  1  A4 FB            ldy $FB                     ; $FDCC: A4 FB
00FDCE  1  E6 FB            inc $FB                     ; $FDCE: E6 FB
00FDD0  1               
00FDD0  1  B1 F7            lda ($F7),y                 ; $FDD0: B1 F7
00FDD2  1  D0 0B            bne UpdateMusicChannel2_HaveCommand
00FDD4  1                                               ; $FDD2: D0 0B
00FDD4  1               
00FDD4  1               ; ----------------------------------------------------------------------------
00FDD4  1               ; A zero byte terminates the complete music sequence.
00FDD4  1               ; ----------------------------------------------------------------------------
00FDD4  1               
00FDD4  1  85 FB            sta $FB                     ; $FDD4: 85 FB
00FDD6  1  85 FA            sta $FA                     ; $FDD6: 85 FA
00FDD8  1  8D F4 07         sta $07F4                   ; $FDD8: 8D F4 07
00FDDB  1               
00FDDB  1  20 60 FA         jsr ConfigurePulse1ControlPreset
00FDDE  1                                               ; $FDDB: 20 60 FA
00FDDE  1               
00FDDE  1  60               rts                         ; $FDDE: 60
00FDDF  1               
00FDDF  1               ; ----------------------------------------------------------------------------
00FDDF  1               ; Decode the command and write the pulse 2 period/control.
00FDDF  1               ; ----------------------------------------------------------------------------
00FDDF  1               
00FDDF  1               UpdateMusicChannel2_HaveCommand: ; $FDDF
00FDDF  1  20 BF FA         jsr LookupAudioControlValue ; $FDDF: 20 BF FA
00FDE2  1  8D F0 07         sta $07F0                   ; $FDE2: 8D F0 07
00FDE5  1               
00FDE5  1  8A               txa                         ; $FDE5: 8A
00FDE6  1  29 3E            and #$3E                    ; $FDE6: 29 3E
00FDE8  1               
00FDE8  1  20 A6 FA         jsr WritePulse2PeriodAfterSweep                   ; $FDE8: 20 A6 FA
00FDEB  1               
00FDEB  1  D0 04            bne UpdateMusicChannel2_SelectControl
00FDED  1                                               ; $FDEB: D0 04
00FDED  1               
00FDED  1  A2 90            ldx #$90                    ; $FDED: A2 90
00FDEF  1  D0 11            bne UpdateMusicChannel2_Write
00FDF1  1                                               ; $FDEF: D0 11
00FDF1  1               
00FDF1  1               UpdateMusicChannel2_SelectControl: ; $FDF1
00FDF1  1  A2 9D            ldx #$9D                    ; $FDF1: A2 9D
00FDF3  1               
00FDF3  1  A5 FC            lda $FC                     ; $FDF3: A5 FC
00FDF5  1  F0 0B            beq UpdateMusicChannel2_Write
00FDF7  1                                               ; $FDF5: F0 0B
00FDF7  1               
00FDF7  1  A2 86            ldx #$86                    ; $FDF7: A2 86
00FDF9  1               
00FDF9  1  AD F0 07         lda $07F0                   ; $FDF9: AD F0 07
00FDFC  1  C9 08            cmp #$08                    ; $FDFC: C9 08
00FDFE  1  B0 02            bcs UpdateMusicChannel2_Write
00FE00  1                                               ; $FDFE: B0 02
00FE00  1               
00FE00  1  A2 82            ldx #$82                    ; $FE00: A2 82
00FE02  1               
00FE02  1               UpdateMusicChannel2_Write:      ; $FE02
00FE02  1  20 71 FA         jsr WritePulse2SweepAndControl                   ; $FE02: 20 71 FA
00FE05  1               
00FE05  1               ; ============================================================================
00FE05  1               ; $FE05-$FE3F
00FE05  1               ; Update the triangle music channel.
00FE05  1               ;
00FE05  1               ; $F9 is the stream cursor and $07F2 is the countdown.
00FE05  1               ; ============================================================================
00FE05  1               
00FE05  1               UpdateTriangleMusicChannel:            ; $FE05
00FE05  1  A4 F9            ldy $F9                     ; $FE05: A4 F9
00FE07  1  F0 36            beq UpdateMusicSequence_Return
00FE09  1                                               ; $FE07: F0 36
00FE09  1               
00FE09  1  AD F2 07         lda $07F2                   ; $FE09: AD F2 07
00FE0C  1  C9 02            cmp #$02                    ; $FE0C: C9 02
00FE0E  1  D0 05            bne UpdateMusicChannel3_Decrement
00FE10  1                                               ; $FE0E: D0 05
00FE10  1               
00FE10  1  A9 00            lda #$00                    ; $FE10: A9 00
00FE12  1  8D 08 40         sta $4008                   ; $FE12: 8D 08 40
00FE15  1               
00FE15  1               UpdateMusicChannel3_Decrement:  ; $FE15
00FE15  1  CE F2 07         dec $07F2                   ; $FE15: CE F2 07
00FE18  1  D0 25            bne UpdateMusicSequence_Return
00FE1A  1                                               ; $FE18: D0 25
00FE1A  1               
00FE1A  1               ; ----------------------------------------------------------------------------
00FE1A  1               ; Fetch and decode the next triangle-channel command.
00FE1A  1               ; ----------------------------------------------------------------------------
00FE1A  1               
00FE1A  1  E6 F9            inc $F9                     ; $FE1A: E6 F9
00FE1C  1               
00FE1C  1  B1 F7            lda ($F7),y                 ; $FE1C: B1 F7
00FE1E  1  20 BF FA         jsr LookupAudioControlValue ; $FE1E: 20 BF FA
00FE21  1               
00FE21  1  8D F2 07         sta $07F2                   ; $FE21: 8D F2 07
00FE24  1               
00FE24  1               ; ----------------------------------------------------------------------------
00FE24  1               ; Select the triangle linear-counter value.
00FE24  1               ; ----------------------------------------------------------------------------
00FE24  1               
00FE24  1  A0 38            ldy #$38                    ; $FE24: A0 38
00FE26  1               
00FE26  1  18               clc                         ; $FE26: 18
00FE27  1  69 FF            adc #$FF                    ; $FE27: 69 FF
00FE29  1               
00FE29  1  C9 0E            cmp #$0E                    ; $FE29: C9 0E
00FE2B  1  B0 03            bcs UpdateMusicChannel3_CheckBank
00FE2D  1                                               ; $FE2B: B0 03
00FE2D  1               
00FE2D  1  0A               asl                         ; $FE2D: 0A
00FE2E  1  0A               asl                         ; $FE2E: 0A
00FE2F  1  A8               tay                         ; $FE2F: A8
00FE30  1               
00FE30  1               UpdateMusicChannel3_CheckBank:  ; $FE30
00FE30  1  A5 FC            lda $FC                     ; $FE30: A5 FC
00FE32  1  D0 02            bne UpdateMusicChannel3_WriteLinear
00FE34  1                                               ; $FE32: D0 02
00FE34  1               
00FE34  1  A0 88            ldy #$88                    ; $FE34: A0 88
00FE36  1               
00FE36  1               UpdateMusicChannel3_WriteLinear: ; $FE36
00FE36  1  8C 08 40         sty $4008                   ; $FE36: 8C 08 40
00FE39  1               
00FE39  1               ; ----------------------------------------------------------------------------
00FE39  1               ; Use the command byte preserved in X by LookupAudioControlValue to select the
00FE39  1               ; triangle timer period.
00FE39  1               ; ----------------------------------------------------------------------------
00FE39  1               
00FE39  1  8A               txa                         ; $FE39: 8A
00FE3A  1  29 3E            and #$3E                    ; $FE3A: 29 3E
00FE3C  1               
00FE3C  1  20 AA FA         jsr WriteTrianglePeriodFromTable
00FE3F  1                                               ; $FE3C: 20 AA FA
00FE3F  1               
00FE3F  1               UpdateMusicSequence_Return:     ; $FE3F
00FE3F  1  60               rts                         ; $FE3F: 60
00FE40  1               
00FE40  1               ; ============================================================================
00FE40  1               ; $FE40-$FFCF
00FE40  1               ; Music sequence, note, duration, envelope, and instrument data.
00FE40  1               ;
00FE40  1               ; This region is consumed by the sequence engine decoded at $FD14-$FE3F.
00FE40  1               ; It includes:
00FE40  1               ;
00FE40  1               ;   - sequence descriptor records
00FE40  1               ;   - note and duration command streams
00FE40  1               ;   - channel-control values
00FE40  1               ;   - instrument and envelope sequences
00FE40  1               ;   - pointers or offsets into the surrounding audio data
00FE40  1               ;
00FE40  1               ; Preserve the bytes exactly. Several streams use zero bytes, negative command
00FE40  1               ; bytes, and compact variable-length records, so speculative instruction
00FE40  1               ; decoding would incorrectly interpret data as executable code.
00FE40  1               ; ============================================================================
00FE40  1               
00FE40  1               MusicSequenceData:         ; $FE40
00FE40  1  08 08 0D 17      .byte $08,$08,$0D,$17,$12,$1C,$21,$26
00FE44  1  12 1C 21 26  
00FE48  1  08 6B FE 15      .byte $08,$6B,$FE,$15,$20,$08,$20,$FF
00FE4C  1  20 08 20 FF  
00FE50  1  28 0C 00 D9      .byte $28,$0C,$00,$D9,$FF,$00,$00,$00
00FE54  1  FF 00 00 00  
00FE58  1  51 FF 6E 2A      .byte $51,$FF,$6E,$2A,$08,$02,$FF,$0E
00FE5C  1  08 02 FF 0E  
00FE60  1               
00FE60  1               MusicSequenceData_FE60:         ; $FE60
00FE60  1  00 08 EA FE      .byte $00,$08,$EA,$FE,$0C,$00,$08,$A5
00FE64  1  0C 00 08 A5  
00FE68  1  FE 1A 2A 18      .byte $FE,$1A,$2A,$18,$04,$18,$18,$58
00FE6C  1  04 18 18 58  
00FE70  1  A0 58 20 04      .byte $A0,$58,$20,$04,$20,$20,$60,$A6
00FE74  1  20 20 60 A6  
00FE78  1  60 26 04 26      .byte $60,$26,$04,$26,$26,$66,$87,$00
00FE7C  1  26 66 87 00  
00FE80  1               
00FE80  1               MusicSequenceData_FE80:         ; $FE80
00FE80  1  45 45 45 98      .byte $45,$45,$45,$98,$78,$18,$04,$18
00FE84  1  78 18 04 18  
00FE88  1  18 58 A7 85      .byte $18,$58,$A7,$85,$04,$82,$18,$81
00FE8C  1  04 82 18 81  
00FE90  1  38 80 18 04      .byte $38,$80,$18,$04,$18,$18,$81,$18
00FE94  1  18 18 81 18  
00FE98  1  82 20 81 18      .byte $82,$20,$81,$18,$80,$20,$04,$20
00FE9C  1  80 20 04 20  
00FEA0  1               
00FEA0  1               MusicSequenceData_FEA0:         ; $FEA0
00FEA0  1  20 81 20 86      .byte $20,$81,$20,$86,$20,$10,$12,$10
00FEA4  1  20 10 12 10  
00FEA8  1  12 02 10 12      .byte $12,$02,$10,$12,$02,$10,$12,$10
00FEAC  1  02 10 12 10  
00FEB0  1  12 02 10 12      .byte $12,$02,$10,$12,$02,$10,$12,$10
00FEB4  1  02 10 12 10  
00FEB8  1  12 02 06 0A      .byte $12,$02,$06,$0A,$0C,$C6,$00,$58
00FEBC  1  0C C6 00 58  
00FEC0  1               
00FEC0  1               MusicSequenceData_FEC0:         ; $FEC0
00FEC0  1  04 18 B8 58      .byte $04,$18,$B8,$58,$04,$18,$B8,$58
00FEC4  1  04 18 B8 58  
00FEC8  1  1C 1E 20 26      .byte $1C,$1E,$20,$26,$2A,$26,$C6,$80
00FECC  1  2A 26 C6 80  
00FED0  1  3C 18 18 18      .byte $3C,$18,$18,$18,$3C,$3C,$3C,$18
00FED4  1  3C 3C 3C 18  
00FED8  1  3C 18 18 18      .byte $3C,$18,$18,$18,$3C,$3C,$3C,$18
00FEDC  1  3C 3C 3C 18  
00FEE0  1               
00FEE0  1               MusicSequenceData_FEE0:         ; $FEE0
00FEE0  1  18 3C 3A 38      .byte $18,$3C,$3A,$38,$36,$38,$3A,$3C
00FEE4  1  36 38 3A 3C  
00FEE8  1  83 1C 98 21      .byte $83,$1C,$98,$21,$E3,$67,$26,$26
00FEEC  1  E3 67 26 26  
00FEF0  1  6A 6E 6A 6E      .byte $6A,$6E,$6A,$6E,$C6,$00,$98,$B8
00FEF4  1  C6 00 98 B8  
00FEF8  1  58 78 78 78      .byte $58,$78,$78,$78,$58,$60,$58,$60
00FEFC  1  58 60 58 60  
00FF00  1               
00FF00  1               MusicSequenceData_FF00:         ; $FF00
00FF00  1  A6 F8 58 18      .byte $A6,$F8,$58,$18,$18,$60,$20,$20
00FF04  1  18 60 20 20  
00FF08  1  66 26 26 6C      .byte $66,$26,$26,$6C,$2C,$2C,$C6,$00
00FF0C  1  2C 2C C6 00  
00FF10  1  58 18 18 78      .byte $58,$18,$18,$78,$38,$38,$58,$18
00FF14  1  38 38 58 18  
00FF18  1  18 78 38 38      .byte $18,$78,$38,$38,$58,$18,$18,$98
00FF1C  1  58 18 18 98  
00FF20  1               
00FF20  1               MusicSequenceData_FF20:         ; $FF20
00FF20  1  C7 2F C7 0D      .byte $C7,$2F,$C7,$0D,$CF,$13,$CF,$8C
00FF24  1  CF 13 CF 8C  
00FF28  1  88 C6 C4 00      .byte $88,$C6,$C4,$00,$87,$2A,$84,$26
00FF2C  1  87 2A 84 26  
00FF30  1  87 22 18 38      .byte $87,$22,$18,$38,$34,$18,$38,$34
00FF34  1  34 18 38 34  
00FF38  1  3C 38 32 3C      .byte $3C,$38,$32,$3C,$38,$32,$84,$18
00FF3C  1  38 32 84 18  
00FF40  1               
00FF40  1               MusicSequenceData_FF40:         ; $FF40
00FF40  1  87 38 38 3A      .byte $87,$38,$38,$3A,$3C,$82,$18,$18
00FF44  1  3C 82 18 18  
00FF48  1  C5 84 98 B8      .byte $C5,$84,$98,$B8,$A6,$9C,$D8,$98
00FF4C  1  A6 9C D8 98  
00FF50  1  98 6B E9 67      .byte $98,$6B,$E9,$67,$E5,$2B,$E7,$25
00FF54  1  E5 2B E7 25  
00FF58  1  E1 DD 85 DB      .byte $E1,$DD,$85,$DB,$1D,$DF,$A0,$86
00FF5C  1  1D DF A0 86  
00FF60  1               
00FF60  1               MusicSequenceData_FF60:         ; $FF60
00FF60  1  AE AA 2F E7      .byte $AE,$AA,$2F,$E7,$3D,$E1,$DD,$85
00FF64  1  3D E1 DD 85  
00FF68  1  FD 19 DD 60      .byte $FD,$19,$DD,$60,$44,$A0,$64,$44
00FF6C  1  44 A0 64 44  
00FF70  1  A4 E7 85 DD      .byte $A4,$E7,$85,$DD,$1B,$DD,$66,$44
00FF74  1  1B DD 66 44  
00FF78  1  66 44 00 85      .byte $66,$44,$00,$85,$44,$87,$42,$85
00FF7C  1  44 87 42 85  
00FF80  1               
00FF80  1               MusicSequenceData_FF80:         ; $FF80
00FF80  1  40 87 3E 84      .byte $40,$87,$3E,$84,$02,$87,$16,$84
00FF84  1  02 87 16 84  
00FF88  1  14 87 12 87      .byte $14,$87,$12,$87,$10,$85,$04,$87
00FF8C  1  10 85 04 87  
00FF90  1  04 12 02 84      .byte $04,$12,$02,$84,$40,$87,$12,$12
00FF94  1  40 87 12 12  
00FF98  1  40 12 84 02      .byte $40,$12,$84,$02,$86,$0C,$04,$08
00FF9C  1  86 0C 04 08  
00FFA0  1               
00FFA0  1               MusicSequenceData_FFA0:         ; $FFA0
00FFA0  1  16 84 3E 87      .byte $16,$84,$3E,$87,$12,$12,$16,$12
00FFA4  1  12 12 16 12  
00FFA8  1  84 14 87 16      .byte $84,$14,$87,$16,$81,$02,$04,$82
00FFAC  1  81 02 04 82  
00FFB0  1  02 81 3E 04      .byte $02,$81,$3E,$04,$82,$02,$87,$16
00FFB4  1  82 02 87 16  
00FFB8  1  85 04 81 2E      .byte $85,$04,$81,$2E,$04,$2E,$04,$09
00FFBC  1  04 2E 04 09  
00FFC0  1               
00FFC0  1               MusicSequenceData_FFC0:         ; $FFC0
00FFC0  1  DD 9C 2B FB      .byte $DD,$9C,$2B,$FB,$BA,$9C,$BA,$DC
00FFC4  1  BA 9C BA DC  
00FFC8  1  98 A6 86 98      .byte $98,$A6,$86,$98,$A6,$9C,$A6,$88
00FFCC  1  A6 9C A6 88  
00FFD0  1               
00FFD0  1               ; ============================================================================
00FFD0  1               ; $FFD0-$FFE9
00FFD0  1               ; Final music/audio sequence data.
00FFD0  1               ; ============================================================================
00FFD0  1               
00FFD0  1               MusicSequenceData_FFD0:         ; $FFD0
00FFD0  1  07 D9 86 09      .byte $07,$D9,$86,$09,$DD,$88,$E6,$A6
00FFD4  1  DD 88 E6 A6  
00FFD8  1  B8 02 12 02      .byte $B8,$02,$12,$02,$12,$02,$12,$02
00FFDC  1  12 02 12 02  
00FFE0  1  52 00            .byte $52,$00
00FFE2  1               
00FFE2  1               ; ============================================================================
00FFE2  1               ; $FFE2-$FFF9
00FFE2  1               ; Unused/padding bytes.
00FFE2  1               ;
00FFE2  1               ; The first two bytes, $52,$00, complete the audio data above. The remaining
00FFE2  1               ; bytes through $FFF9 are $FF padding.
00FFE2  1               ; ============================================================================
00FFE2  1               
00FFE2  1               UnusedRomPadding:                ; $FFE2
00FFE2  1  FF FF FF FF      .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
00FFE6  1  FF FF FF FF  
00FFEA  1  FF FF FF FF      .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
00FFEE  1  FF FF FF FF  
00FFF2  1  FF FF FF FF      .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
00FFF6  1  FF FF FF FF  
00FFFA  1               
00FFFA  1               ; ============================================================================
00FFFA  1               ; $FFFA-$FFFF
00FFFA  1               ; 6502 interrupt vectors.
00FFFA  1               ;
00FFFA  1               ; Each vector is stored little-endian:
00FFFA  1               ;
00FFFA  1               ;   NMI:   $C046
00FFFA  1               ;   RESET: $C40B
00FFFA  1               ;   IRQ:   $C43E
00FFFA  1               ; ============================================================================
00FFFA  1               
00FFFA  1               InterruptVectors:               ; $FFFA
00FFFA  1               
00FFFA  1               NmiVectorWord:                      ; $FFFA
00FFFA  1  46 C0            .word $C046                 ; $FFFA: 46 C0
00FFFC  1               
00FFFC  1               ResetVectorWord:                    ; $FFFC
00FFFC  1  0B C4            .word $C40B                 ; $FFFC: 0B C4
00FFFE  1               
00FFFE  1               IrqBrkVectorWord:                   ; $FFFE
00FFFE  1  3E C4            .word $C43E                 ; $FFFE: 3E C4
010000  1               
010000  1               ; ============================================================================
010000  1               ; End of 16 KB PRG-ROM.
010000  1               ;
010000  1               ; CPU range completed: $C000-$FFFF
010000  1               ; ROM range completed: $0000-$3FFF
010000  1               ; ============================================================================
010000  1               
